madman.analysis.ehden

Electron / hole density.

  1r"""Electron / hole density."""
  2
  3from __future__ import annotations
  4from collections.abc import Sequence
  5from numbers import Real
  6from sys import modules
  7from typing import Any, Self, Type
  8
  9import numpy as np
 10from matplotlib import pyplot as plt
 11
 12from madman.analysis.edos import (
 13    ElectronDensityOfStates,
 14    ResolvedElectronDensityOfStates,
 15    BandResolvedElectronDensityOfStates,
 16    CellResolvedElectronDensityOfStates,
 17)
 18from madman.analysis.ejdos import (
 19    ElectronJointDensityOfStates,
 20    ResolvedElectronJointDensityOfStates,
 21    BandResolvedElectronJointDensityOfStates,
 22    CellResolvedElectronJointDensityOfStates,
 23)
 24from madman.analysis.spectrum import (
 25    EnergySpectrumMeta,
 26    EnergySpectrum,
 27    ResolvedEnergySpectrumMeta,
 28    ResolvedEnergySpectrum,
 29)
 30from madman.constant import Constant
 31from madman.utilities import correlate1d
 32
 33
 34def ret_fd_occups(
 35    energies: Sequence[Real, ...],
 36    *,
 37    fermi_lv: Real = 0.0,
 38    temperature: Real = 300.0,
 39) -> np.ndarray[float]:
 40    r"""Return Fermi-Dirac occupations.
 41
 42    Args:
 43        energies: Electron energies [$\mathrm{eV}$].
 44        fermi_lv: Fermi level [$\mathrm{eV}$].
 45        temperature: Temperature [$\mathrm{K}$].
 46
 47    Returns:
 48        Fermi-Dirac occupations.
 49
 50    Raises:
 51        ValueError: If temperature is non-positive.
 52    """
 53    energies = np.asarray(energies, dtype=float).flatten()
 54    if temperature <= 0.0:
 55        raise ValueError("Non-positive temperature!")
 56    red_energies = (energies - fermi_lv) / (Constant.k * temperature)
 57    occups = np.where(
 58        red_energies == 0.0,
 59        0.5,
 60        1.0 / (1.0 + np.exp(red_energies)),
 61    )
 62    return occups
 63
 64
 65class SpectralCarrierDensityMeta(EnergySpectrumMeta):
 66    r"""Metaclass of SpectralCarrierDensity."""
 67
 68    @property
 69    def std_axes(cls) -> plt.Axes:
 70        r"""Standard axes to plot spectral carrier density.
 71
 72        Returns:
 73            Plot axes.
 74        """
 75        _, ax = plt.subplots(tight_layout=True)
 76        ax.set_xlabel(r"Electron energy / $\mathrm{eV}$")
 77
 78        if "Carrier" in cls.__name__:
 79            ax.set_ylabel(r"Spectral carrier density / $\mathrm{eV^{-1}}$")
 80        if "Electron" in cls.__name__:
 81            ax.set_ylabel(r"Spectral electron density / $\mathrm{eV^{-1}}$")
 82        if "Hole" in cls.__name__:
 83            ax.set_ylabel(r"Spectral hole density / $\mathrm{eV^{-1}}$")
 84
 85        return ax
 86
 87
 88class SpectralCarrierDensity(
 89    EnergySpectrum, metaclass=SpectralCarrierDensityMeta
 90):
 91    r"""Spectral carrier density.
 92
 93    Note:
 94        `energies`: Electron energies [$\mathrm{eV}$].
 95        `values`: Spectral carrier density values [$\mathrm{eV^{-1}}$].
 96    """
 97
 98    def __init__(
 99        self,
100        edos: ElectronDensityOfStates,
101        *,
102        fermi_lv: Real = 0.0,
103        temperature: Real = 300.0,
104    ) -> None:
105        r"""Initialize SpectralCarrierDensity object.
106
107        Args:
108            edos: Electron density of states.
109            fermi_lv: Fermi level [$\mathrm{eV}$].
110            temperature: Temperature [$\mathrm{K}$].
111
112        Raises:
113            TypeError: If `edos` is not a ElectronDensityOfStates object.
114            ValueError: If temperature is non-positive.
115        """
116        if not isinstance(edos, ElectronDensityOfStates):
117            raise TypeError("Not a ElectronDensityOfStates object!")
118        if temperature <= 0.0:
119            raise ValueError("Non-positive temperature!")
120
121        self._edos = edos
122        self._fermi_lv = float(fermi_lv)
123        self._temperature = float(temperature)
124        self._energies = edos.energies
125
126        if isinstance(self, SpectralElectronDensity):
127            occups = ret_fd_occups(
128                self.energies,
129                fermi_lv=self.fermi_lv,
130                temperature=self.temperature,
131            )
132        elif isinstance(self, SpectralHoleDensity):
133            occups = 1.0 - ret_fd_occups(
134                self.energies,
135                fermi_lv=self.fermi_lv,
136                temperature=self.temperature,
137            )
138        else:
139            occups = 1.0
140
141        self._values = occups * edos.values
142        self._integr = np.trapz(self._values, x=self._energies)
143        self._sp_eden = None
144        self._sp_hden = None
145
146    def __add__(self, other: Self) -> Self:
147        r"""Add spectral carrier density.
148
149        Args:
150            other: Spectral carrier density to add.
151
152        Returns:
153            Sum of `self` and `other`.
154
155        Raises:
156            TypeError: If `self` and `other` have incompatible types.
157            ValueError: If `self` and `other`have incompatible Fermi levels.
158            ValueError: If `self` and `other`have incompatible temperatures.
159        """
160        if type(self) != type(other):
161            raise TypeError("Incompatible types!")
162        if self.fermi_lv != other.fermi_lv:
163            raise ValueError("Incompatible Fermi levels!")
164        if self.temperature != other.temperature:
165            raise ValueError("Incompatible temperatures!")
166        edos = self.edos + other.edos
167        return type(self)(
168            edos, fermi_lv=self.fermi_lv, temperature=self.temperature
169        )
170
171    @property
172    def edos(self) -> ElectronDensityOfStates:
173        r"""Electron density of states."""
174        return self._edos
175
176    @property
177    def fermi_lv(self) -> float:
178        r"""Fermi level [$\mathrm{eV}$]."""
179        return self._fermi_lv
180
181    @property
182    def temperature(self) -> float:
183        r"""Temperature [$\mathrm{K}$]."""
184        return self._temperature
185
186    @property
187    def sp_eden(self) -> SpectralElectronDensity:
188        r"""Spectral electron density."""
189        if self._sp_eden is None:
190            if isinstance(self, SpectralElectronDensity):
191                self._sp_eden = self
192            else:
193                self._sp_eden = SpectralElectronDensity(
194                    self.edos,
195                    fermi_lv=self.fermi_lv,
196                    temperature=self.temperature,
197                )
198        return self._sp_eden
199
200    @property
201    def sp_hden(self) -> SpectralHoleDensity:
202        r"""Spectral hole density."""
203        if self._sp_hden is None:
204            if isinstance(self, SpectralHoleDensity):
205                self._sp_hden = self
206            else:
207                self._sp_hden = SpectralHoleDensity(
208                    self.edos,
209                    fermi_lv=self.fermi_lv,
210                    temperature=self.temperature,
211                )
212        return self._sp_hden
213
214    def ret_zero(self) -> Self:
215        r"""Return zero spectral carrier density."""
216        return type(self).zero(
217            self.energies, fermi_lv=self.fermi_lv, temperature=self.temperature
218        )
219
220    def ret_smeared(self, *, sigma: Real) -> Self:
221        r"""Return smeared spectral carrier density.
222
223        Args:
224            sigma: Standard deviation for Gaussian kernel.
225
226        Returns:
227            Smeared spectral carrier density.
228        """
229        edos = self.edos.ret_smeared(sigma=sigma)
230        return type(self)(
231            edos, fermi_lv=self.fermi_lv, temperature=self.temperature
232        )
233
234    def ret_band_rsv(
235        self, *, threshold: Real = 0.0
236    ) -> BandResolvedSpectralCarrierDensity:
237        r"""Return band resolved spectral carrier density.
238
239        Args:
240            threshold: Threshold below which electron density of states values
241                are rounded to zero [$\mathrm{eV^{-1}}$].
242
243        Returns:
244            Band resolved spectral carrier density.
245        """
246        rsv_edos = self.edos.ret_band_rsv(threshold=threshold)
247        return type(self).band_rsv(
248            rsv_edos, fermi_lv=self.fermi_lv, temperature=self.temperature
249        )
250
251    def calc_ejdos(self) -> ElectronJointDensityOfStates:
252        r"""Calculate electron joint density of states.
253
254        Returns:
255            Electron joint density of states.
256        """
257        ejdos_energies, ejdos_values = correlate1d(
258            self.energies, self.sp_eden.values, self.sp_hden.values
259        )
260        return ElectronJointDensityOfStates(ejdos_energies, ejdos_values)
261
262    def plot_fermi_lv(
263        self,
264        *,
265        ax: plt.Axes,
266        color: str | None = None,
267        label: str | None = None,
268    ) -> plt.Figure:
269        r"""Plot Fermi level.
270
271        Args:
272            ax: Plot axes; if None, new figure and axes are created.
273            color: Line color.
274            label: Line label.
275
276        Returns:
277            Plot figure.
278        """
279        ax.axvline(self.fermi_lv, linestyle="--", color=color, label=label)
280        return ax.get_figure()
281
282    @classmethod
283    def zero(
284        cls,
285        energies: Sequence[Real, ...],
286        *,
287        d_energy: Real | None = None,
288        fermi_lv: Real = 0.0,
289        temperature: Real = 300.0,
290    ) -> np.ndarray[float]:
291        r"""Zero spectral carrier density.
292
293        Args:
294            energies: Electron energies [$\mathrm{eV}$].
295            d_energy: Target electron energy increment [$\mathrm{eV}$].
296            fermi_lv: Fermi level [$\mathrm{eV}$].
297            temperature: Temperature [$\mathrm{K}$].
298
299        Returns:
300            Zero spectral carrier density.
301        """
302        edos = ElectronDensityOfStates.zero(energies, d_energy=d_energy)
303        return cls(edos, fermi_lv=fermi_lv, temperature=temperature)
304
305    @classmethod
306    def piecewise_constant(
307        cls,
308        energy_a: Real,
309        energy_b: Real,
310        d_energy: Real,
311        *,
312        amplitudes: Sequence[Real, ...],
313        low_bounds: Sequence[Real, ...],
314        upp_bounds: Sequence[Real, ...],
315        fermi_lv: Real = 0.0,
316        temperature: Real = 300.0,
317    ) -> Self:
318        r"""Piecewise constant spectral carrier density.
319
320        Args:
321            energy_a: Electron energy minimum [$\mathrm{eV}$].
322            energy_b: Electron energy maximum [$\mathrm{eV}$].
323            d_energy: Target electron energy increment [$\mathrm{eV}$].
324            amplitudes: Electron density of states piece amplitudes
325                [$\mathrm{eV^{-1}}$].
326            low_bounds: Electron density of states piece lower bounds
327                [$\mathrm{eV}$].
328            upp_bounds: Electron density of states piece upper bounds
329                [$\mathrm{eV}$].
330            fermi_lv: Fermi level [$\mathrm{eV}$].
331            temperature: Temperature [$\mathrm{K}$].
332
333        Returns:
334            Piecewise constant spectral carrier density.
335        """
336        edos = ElectronDensityOfStates.piecewise_constant(
337            energy_a,
338            energy_b,
339            d_energy,
340            amplitudes=amplitudes,
341            low_bounds=low_bounds,
342            upp_bounds=upp_bounds,
343        )
344        return cls(edos, fermi_lv=fermi_lv, temperature=temperature)
345
346
347class SpectralElectronDensity(SpectralCarrierDensity):
348    r"""Spectral electron density.
349
350    Note:
351        `energies`: Electron energies [$\mathrm{eV}$].
352        `values`: Spectral electron density values [$\mathrm{eV^{-1}}$].
353    """
354
355
356class SpectralHoleDensity(SpectralCarrierDensity):
357    r"""Spectral hole density.
358
359    Note:
360        `energies`: Electron energies [$\mathrm{eV}$].
361        `values`: Spectral hole density values [$\mathrm{eV^{-1}}$].
362    """
363
364
365class ResolvedSpectralCarrierDensityMeta(ResolvedEnergySpectrumMeta):
366    r"""Metaclass of ResolvedSpectralCarrierDensity."""
367
368    @property
369    def rsv_edos(cls) -> Type:
370        r"""Associated resolved electron density of states class."""
371        module = modules[cls.__module__]
372        name = (
373            cls.__name__[: cls.__name__.index("Resolved") + len("Resolved")]
374            + "ElectronDensityOfStates"
375        )
376        return getattr(module, name)
377
378    @property
379    def rsv_sp_eden(cls) -> Type:
380        r"""Associated resolved spectral electron density class."""
381        module = modules[cls.__module__]
382        name = cls.__name__.replace("Carrier", "Electron").replace(
383            "Hole", "Electron"
384        )
385        return getattr(module, name)
386
387    @property
388    def rsv_sp_hden(cls) -> Type:
389        r"""Associated resolved spectral hole density class."""
390        module = modules[cls.__module__]
391        name = cls.__name__.replace("Carrier", "Hole").replace(
392            "Electron", "Hole"
393        )
394        return getattr(module, name)
395
396    @property
397    def rsv_ejdos(cls) -> Type:
398        r"""Associated resolved electron joint density of states class."""
399        module = modules[cls.__module__]
400        name = (
401            cls.__name__[: cls.__name__.index("Resolved") + len("Resolved")]
402            + "ElectronJointDensityOfStates"
403        )
404        return getattr(module, name)
405
406
407class ResolvedSpectralCarrierDensity(
408    ResolvedEnergySpectrum, metaclass=ResolvedSpectralCarrierDensityMeta
409):
410    r"""Resolved spectral carrier density.
411
412    Note:
413        `energies`: Electron energies [$\mathrm{eV}$].
414        `rsv_values`: Resolved spectral carrier density values
415            [$\mathrm{eV^{-1}}$].
416    """
417
418    def __init__(
419        self,
420        rsv_edos: ResolvedElectronDensityOfStates,
421        *,
422        fermi_lv: Real = 0.0,
423        temperature: Real = 300.0,
424    ) -> None:
425        r"""Initialize ResolvedSpectralCarrierDensity object.
426
427        Args:
428            rsv_edos: Resolved electron density of states.
429            fermi_lv: Fermi level [$\mathrm{eV}$].
430            temperature: Temperature [$\mathrm{K}$].
431
432        Raises:
433            TypeError: If resolved electron density of states is incompatible.
434            ValueError: If temperature is non-positive.
435        """
436        if type(rsv_edos) != type(self).rsv_edos:
437            raise TypeError("Incompatible resolved electron density of states!")
438        if temperature <= 0.0:
439            raise ValueError("Non-positive temperature!")
440
441        self._rsv_edos = rsv_edos
442        self._fermi_lv = float(fermi_lv)
443        self._temperature = float(temperature)
444        self._energies = self.rsv_edos.energies
445
446        if isinstance(self, ResolvedSpectralElectronDensity):
447            occups = ret_fd_occups(
448                self.energies,
449                fermi_lv=self.fermi_lv,
450                temperature=self.temperature,
451            )
452        elif isinstance(self, ResolvedSpectralHoleDensity):
453            occups = 1.0 - ret_fd_occups(
454                self.energies,
455                fermi_lv=self.fermi_lv,
456                temperature=self.temperature,
457            )
458        else:
459            occups = 1.0
460
461        self._rsv_values = {
462            feat: occups * edos_values
463            for feat, edos_values in self.rsv_edos.rsv_values.items()
464        }
465        self._rsv_integr = {
466            feat: np.trapz(values, x=self.energies)
467            for feat, values in self._rsv_values.items()
468        }
469        self._total = type(self).total(
470            self.rsv_edos.total,
471            fermi_lv=self.fermi_lv,
472            temperature=self.temperature,
473        )
474        self._rsv_sp_eden = None
475        self._rsv_sp_hden = None
476
477    @property
478    def rsv_edos(self) -> ResolvedElectronDensityOfStates:
479        r"""Resolved electron density of states."""
480        return self._rsv_edos
481
482    @property
483    def fermi_lv(self) -> float:
484        r"""Fermi level [$\mathrm{eV}$]."""
485        return self._fermi_lv
486
487    @property
488    def temperature(self) -> float:
489        r"""Temperature [$\mathrm{K}$]."""
490        return self._temperature
491
492    @property
493    def rsv_sp_eden(self) -> ResolvedSpectralElectronDensity:
494        r"""Resolved spectral electron density."""
495        if self._rsv_sp_eden is None:
496            if isinstance(self, ResolvedSpectralElectronDensity):
497                self._rsv_sp_eden = self
498            else:
499                self._rsv_sp_eden = type(self).rsv_sp_eden(
500                    self.rsv_edos,
501                    fermi_lv=self.fermi_lv,
502                    temperature=self.temperature,
503                )
504        return self._rsv_sp_eden
505
506    @property
507    def rsv_sp_hden(self) -> ResolvedSpectralHoleDensity:
508        r"""Resolved spectral hole density."""
509        if self._rsv_sp_hden is None:
510            if isinstance(self, ResolvedSpectralHoleDensity):
511                self._rsv_sp_hden = self
512            else:
513                self._rsv_sp_hden = type(self).rsv_sp_hden(
514                    self.rsv_edos,
515                    fermi_lv=self.fermi_lv,
516                    temperature=self.temperature,
517                )
518        return self._rsv_sp_hden
519
520    def ret_zero(self) -> Self:
521        r"""Return zero resolved spectral carrier density."""
522        return type(self).zero(
523            self.rsv_edos.energies,
524            self.rsv_edos.rsv_values.keys(),
525            fermi_lv=self.fermi_lv,
526            temperature=self.temperature,
527        )
528
529    def ret_smeared(self, *, sigma: Real) -> Self:
530        r"""Return smeared resolved spectral carrier density.
531
532        Args:
533            sigma: Standard deviation for Gaussian kernel.
534
535        Returns:
536            Smeared resolved spectral carrier density.
537        """
538        rsv_edos = self.rsv_edos.ret_smeared(sigma=sigma)
539        return type(self)(
540            rsv_edos, fermi_lv=self.fermi_lv, temperature=self.temperature
541        )
542
543    def calc_rsv_ejdos(self) -> ResolvedElectronJointDensityOfStates:
544        r"""Calculate resolved electron joint density of states."""
545        rsv_ejdos_values = {}
546        for feat_e, values_e in self.rsv_sp_eden.rsv_values.items():
547            for feat_h, values_h in self.rsv_sp_hden.rsv_values.items():
548                if isinstance(self, CellResolvedSpectralCarrierDensity):
549                    pair = feat_e + feat_h
550                    if pair not in {"ii", "vi", "ic", "vc"}:
551                        continue
552                else:
553                    pair = (feat_e, feat_h)
554
555                ejdos_energies, ejdos_values = correlate1d(
556                    self.energies, values_e, values_h
557                )
558                rsv_ejdos_values[pair] = ejdos_values
559
560        return type(self).rsv_ejdos(ejdos_energies, rsv_ejdos_values)
561
562    def plot_fermi_lv(
563        self,
564        *,
565        ax: plt.Axes,
566        color: str | None = None,
567        label: str | None = None,
568    ) -> plt.Figure:
569        r"""Plot Fermi level.
570
571        Args:
572            ax: Plot axes; if None, new figure and axes are created.
573            color: Line color.
574            label: Line label.
575
576        Returns:
577            Plot figure.
578        """
579        ax.axvline(self.fermi_lv, linestyle="--", color=color, label=label)
580        return ax.get_figure()
581
582    @classmethod
583    def zero(
584        cls,
585        energies: Sequence[Real, ...],
586        features: Sequence[Any, ...],
587        *,
588        d_energy: Real | None = None,
589        fermi_lv: Real = 0.0,
590        temperature: Real = 300.0,
591    ) -> Self:
592        r"""Zero resolved spectral carrier density.
593
594        Args:
595            energies: Resolved spectral carrier density energies
596                [$\mathrm{eV}$].
597            features: Resolved spectral carrier density features.
598            d_energy: Target electron energy increment [$\mathrm{eV}$].
599            fermi_lv: Fermi level [$\mathrm{eV}$].
600            temperature: Temperature [$\mathrm{K}$].
601
602        Returns:
603            Zero resolved spectral carrier density.
604        """
605        rsv_edos = cls.rsv_edos.zero(energies, features, d_energy=d_energy)
606        return cls(rsv_edos, fermi_lv=fermi_lv, temperature=temperature)
607
608
609class ResolvedSpectralElectronDensity(ResolvedSpectralCarrierDensity):
610    r"""Resolved spectral electron density.
611
612    Note:
613        `energies`: Electron energies [$\mathrm{eV}$].
614        `rsv_values`: Resolved spectral electron density values
615            [$\mathrm{eV^{-1}}$].
616    """
617
618
619class ResolvedSpectralHoleDensity(ResolvedSpectralCarrierDensity):
620    r"""Resolved spectral hole density.
621
622    Note:
623        `energies`: Electron energies [$\mathrm{eV}$].
624        `rsv_values`: Resolved spectral hole density values
625            [$\mathrm{eV^{-1}}$].
626    """
627
628
629class BandResolvedSpectralCarrierDensity(ResolvedSpectralCarrierDensity):
630    r"""Band resolved spectral carrier density.
631
632    Note:
633        `energies`: Electron energies [$\mathrm{eV}$].
634        `rsv_values`: Band resolved spectral carrier density values
635            [$\mathrm{eV^{-1}}$].
636
637    Note:
638        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
639    """
640
641    def ret_rsv_fill_type(self, *, tolerance: Real = 0.0) -> dict[int, str]:
642        r"""Return band resolved fill type.
643
644        Args:
645            tolerance: Minimum distance between Fermi level and band edges
646                for band fill type to be determined [$\mathrm{eV}$].
647
648        Returns:
649            Band resolved fill type.
650        """
651        rsv_fill_type = {}
652        for i, edos_values in self.rsv_edos.rsv_values.items():
653            band_energies = self.energies[edos_values > 0.0]
654            if (
655                np.amin(band_energies) < self.fermi_lv - tolerance
656                and np.amax(band_energies) > self.fermi_lv + tolerance
657            ):
658                rsv_fill_type[i] = "metallic"
659            elif np.all(band_energies < self.fermi_lv + tolerance):
660                rsv_fill_type[i] = "filled"
661            elif np.all(band_energies > self.fermi_lv - tolerance):
662                rsv_fill_type[i] = "empty"
663            else:
664                rsv_fill_type[i] = "undetermined"
665        return rsv_fill_type
666
667    def ret_cell_rsv(
668        self, cell_type, *, tolerance: Real = 0.0
669    ) -> list[CellResolvedSpectralCarrierDensity, ...]:
670        r"""Return cell resolved spectral carrier densities.
671
672        Args:
673            cell_type: Cell type ('sq' ord 'ib').
674            tolerance: Minimum distance between Fermi level and band edges
675                for band fill type to be determined [$\mathrm{eV}$].
676
677        Returns:
678            List of cell resolved spectral carrier densities.
679
680        Raises:
681            ValueError: If cell type is not 'sq' or 'ib'.
682        """
683        if cell_type not in {"sq", "ib"}:
684            raise ValueError("Cell type must be 'sq' or 'ib'!")
685
686        cell_rsv_seq = []
687        rsv_fill_type = self.ret_rsv_fill_type(tolerance=tolerance)
688
689        if cell_type == "sq":
690
691            if set(rsv_fill_type.values()) == {"filled", "empty"}:
692                cell_rsv_edos_values = {"v": 0, "c": 0}
693                rsv_edos_values = self.rsv_edos.rsv_values
694                for band_i, fill_type in rsv_fill_type.items():
695                    edos_values = rsv_edos_values[band_i]
696                    if fill_type == "filled":
697                        cell_rsv_edos_values["v"] += edos_values
698                    if fill_type == "empty":
699                        cell_rsv_edos_values["c"] += edos_values
700                cell_rsv_edos = CellResolvedElectronDensityOfStates(
701                    self.energies, cell_rsv_edos_values
702                )
703                cell_rsv = type(self).total.cell_rsv(
704                    cell_rsv_edos,
705                    fermi_lv=self.fermi_lv,
706                    temperature=self.temperature,
707                )
708                cell_rsv_seq.append(cell_rsv)
709
710        elif cell_type == "ib":
711
712            if set(rsv_fill_type.values()) == {"filled", "metallic", "empty"}:
713                cell_rsv_edos_values = {"v": 0, "i": 0, "c": 0}
714                rsv_edos_values = self.rsv_edos.rsv_values
715                for band_i, fill_type in rsv_fill_type.items():
716                    edos_values = rsv_edos_values[band_i]
717                    if fill_type == "filled":
718                        cell_rsv_edos_values["v"] += edos_values
719                    if fill_type == "metallic":
720                        cell_rsv_edos_values["i"] += edos_values
721                    if fill_type == "empty":
722                        cell_rsv_edos_values["c"] += edos_values
723                cell_rsv_edos = CellResolvedElectronDensityOfStates(
724                    self.energies, cell_rsv_edos_values
725                )
726                cell_rsv = type(self).total.cell_rsv(
727                    cell_rsv_edos,
728                    fermi_lv=self.fermi_lv,
729                    temperature=self.temperature,
730                )
731                cell_rsv_seq.append(cell_rsv)
732
733            if set(rsv_fill_type.values()) == {"filled", "empty"}:
734                rsv_edos_values = self.rsv_edos.rsv_values
735
736                rsv_edos_values_filled = [
737                    rsv_edos_values[band_i]
738                    for band_i, fill_type in rsv_fill_type.items()
739                    if fill_type == "filled"
740                ]
741                rsv_edos_values_filled.sort(key=lambda x: x.min())
742
743                rsv_edos_values_empty = [
744                    rsv_edos_values[band_i]
745                    for band_i, fill_type in rsv_fill_type.items()
746                    if fill_type == "empty"
747                ]
748                rsv_edos_values_empty.sort(key=lambda x: x.min())
749
750                if len(rsv_edos_values_empty) > 1:
751                    cell_rsv_edos_values = {
752                        "v": sum(rsv_edos_values_filled),
753                        "i": rsv_edos_values_empty[0],
754                        "c": sum(rsv_edos_values_empty[1:]),
755                    }
756                    cell_rsv_edos = CellResolvedElectronDensityOfStates(
757                        self.energies, cell_rsv_edos_values
758                    )
759                    cell_rsv = type(self).total.cell_rsv(
760                        cell_rsv_edos,
761                        fermi_lv=self.fermi_lv,
762                        temperature=self.temperature,
763                    )
764                    cell_rsv_seq.append(cell_rsv)
765
766                if len(rsv_edos_values_filled) > 1:
767                    cell_rsv_edos_values = {
768                        "v": sum(rsv_edos_values_filled[:-1]),
769                        "i": rsv_edos_values_filled[-1],
770                        "c": sum(rsv_edos_values_empty),
771                    }
772                    cell_rsv_edos = CellResolvedElectronDensityOfStates(
773                        self.energies, cell_rsv_edos_values
774                    )
775                    cell_rsv = type(self).total.cell_rsv(
776                        cell_rsv_edos,
777                        fermi_lv=self.fermi_lv,
778                        temperature=self.temperature,
779                    )
780                    cell_rsv_seq.append(cell_rsv)
781
782        return cell_rsv_seq
783
784
785class BandResolvedSpectralElectronDensity(
786    ResolvedSpectralElectronDensity, BandResolvedSpectralCarrierDensity
787):
788    r"""Band resolved spectral electron density.
789
790    Note:
791        `energies`: Electron energies [$\mathrm{eV}$].
792        `rsv_values`: Band resolved spectral electron density values
793            [$\mathrm{eV^{-1}}$].
794
795    Note:
796        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
797    """
798
799
800class BandResolvedSpectralHoleDensity(
801    ResolvedSpectralHoleDensity, BandResolvedSpectralCarrierDensity
802):
803    r"""Band resolved spectral hole density.
804
805    Note:
806        `energies`: Electron energies [$\mathrm{eV}$].
807        `rsv_values`: Band resolved spectral hole density values
808            [$\mathrm{eV^{-1}}$].
809
810    Note:
811        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
812    """
813
814
815class CellResolvedSpectralCarrierDensity(ResolvedSpectralCarrierDensity):
816    r"""Cell resolved spectral carrier density.
817
818    Note:
819        `energies`: Electron energies [$\mathrm{eV}$].
820        `rsv_values`: Cell resolved spectral carrier density values
821            [$\mathrm{eV^{-1}}$].
822
823    Note:
824        See `madman.analysis.spectrum.CellResolvedEnergySpectrum` for details.
825    """
826    def ret_rsv_fill_type(self, *, tolerance: Real = 0.0) -> dict[int, str]:
827        r"""Return cell resolved fill type.
828
829        Args:
830            tolerance: Minimum distance between Fermi level and band edges
831                for band fill type to be determined [$\mathrm{eV}$].
832
833        Returns:
834            Cell resolved fill type.
835        """
836        rsv_fill_type = {}
837        for i, edos_values in self.rsv_edos.rsv_values.items():
838            band_energies = self.energies[edos_values > 0.0]
839            if (
840                np.amin(band_energies) < self.fermi_lv - tolerance
841                and np.amax(band_energies) > self.fermi_lv + tolerance
842            ):
843                rsv_fill_type[i] = "metallic"
844            elif np.all(band_energies < self.fermi_lv + tolerance):
845                rsv_fill_type[i] = "filled"
846            elif np.all(band_energies > self.fermi_lv - tolerance):
847                rsv_fill_type[i] = "empty"
848            else:
849                rsv_fill_type[i] = "undetermined"
850        return rsv_fill_type
851
852
853class CellResolvedSpectralElectronDensity(
854    ResolvedSpectralElectronDensity, CellResolvedSpectralCarrierDensity
855):
856    r"""Cell resolved spectral electron density.
857
858    Note:
859        `energies`: Electron energies [$\mathrm{eV}$].
860        `rsv_values`: Cell resolved spectral electron density values
861            [$\mathrm{eV^{-1}}$].
862
863    Note:
864        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
865    """
866
867
868class CellResolvedSpectralHoleDensity(
869    ResolvedSpectralHoleDensity, CellResolvedSpectralCarrierDensity
870):
871    r"""Cell resolved spectral hole density.
872
873    Note:
874        `energies`: Electron energies [$\mathrm{eV}$].
875        `rsv_values`: Cell resolved spectral hole density values
876            [$\mathrm{eV^{-1}}$].
877
878    Note:
879        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
880    """
def ret_fd_occups( energies: collections.abc.Sequence[numbers.Real, ...], *, fermi_lv: numbers.Real = 0.0, temperature: numbers.Real = 300.0) -> numpy.ndarray[float]:
35def ret_fd_occups(
36    energies: Sequence[Real, ...],
37    *,
38    fermi_lv: Real = 0.0,
39    temperature: Real = 300.0,
40) -> np.ndarray[float]:
41    r"""Return Fermi-Dirac occupations.
42
43    Args:
44        energies: Electron energies [$\mathrm{eV}$].
45        fermi_lv: Fermi level [$\mathrm{eV}$].
46        temperature: Temperature [$\mathrm{K}$].
47
48    Returns:
49        Fermi-Dirac occupations.
50
51    Raises:
52        ValueError: If temperature is non-positive.
53    """
54    energies = np.asarray(energies, dtype=float).flatten()
55    if temperature <= 0.0:
56        raise ValueError("Non-positive temperature!")
57    red_energies = (energies - fermi_lv) / (Constant.k * temperature)
58    occups = np.where(
59        red_energies == 0.0,
60        0.5,
61        1.0 / (1.0 + np.exp(red_energies)),
62    )
63    return occups

Return Fermi-Dirac occupations.

Arguments:
  • energies: Electron energies [$\mathrm{eV}$].
  • fermi_lv: Fermi level [$\mathrm{eV}$].
  • temperature: Temperature [$\mathrm{K}$].
Returns:

Fermi-Dirac occupations.

Raises:
  • ValueError: If temperature is non-positive.
class SpectralCarrierDensityMeta(madman.analysis.spectrum.EnergySpectrumMeta):
66class SpectralCarrierDensityMeta(EnergySpectrumMeta):
67    r"""Metaclass of SpectralCarrierDensity."""
68
69    @property
70    def std_axes(cls) -> plt.Axes:
71        r"""Standard axes to plot spectral carrier density.
72
73        Returns:
74            Plot axes.
75        """
76        _, ax = plt.subplots(tight_layout=True)
77        ax.set_xlabel(r"Electron energy / $\mathrm{eV}$")
78
79        if "Carrier" in cls.__name__:
80            ax.set_ylabel(r"Spectral carrier density / $\mathrm{eV^{-1}}$")
81        if "Electron" in cls.__name__:
82            ax.set_ylabel(r"Spectral electron density / $\mathrm{eV^{-1}}$")
83        if "Hole" in cls.__name__:
84            ax.set_ylabel(r"Spectral hole density / $\mathrm{eV^{-1}}$")
85
86        return ax

Metaclass of SpectralCarrierDensity.

std_axes: matplotlib.axes._axes.Axes
69    @property
70    def std_axes(cls) -> plt.Axes:
71        r"""Standard axes to plot spectral carrier density.
72
73        Returns:
74            Plot axes.
75        """
76        _, ax = plt.subplots(tight_layout=True)
77        ax.set_xlabel(r"Electron energy / $\mathrm{eV}$")
78
79        if "Carrier" in cls.__name__:
80            ax.set_ylabel(r"Spectral carrier density / $\mathrm{eV^{-1}}$")
81        if "Electron" in cls.__name__:
82            ax.set_ylabel(r"Spectral electron density / $\mathrm{eV^{-1}}$")
83        if "Hole" in cls.__name__:
84            ax.set_ylabel(r"Spectral hole density / $\mathrm{eV^{-1}}$")
85
86        return ax

Standard axes to plot spectral carrier density.

Returns:

Plot axes.

Inherited Members
builtins.type
type
mro
madman.analysis.spectrum.EnergySpectrumMeta
rsv
band_rsv
cell_rsv
class SpectralCarrierDensity(madman.analysis.spectrum.EnergySpectrum):
 89class SpectralCarrierDensity(
 90    EnergySpectrum, metaclass=SpectralCarrierDensityMeta
 91):
 92    r"""Spectral carrier density.
 93
 94    Note:
 95        `energies`: Electron energies [$\mathrm{eV}$].
 96        `values`: Spectral carrier density values [$\mathrm{eV^{-1}}$].
 97    """
 98
 99    def __init__(
100        self,
101        edos: ElectronDensityOfStates,
102        *,
103        fermi_lv: Real = 0.0,
104        temperature: Real = 300.0,
105    ) -> None:
106        r"""Initialize SpectralCarrierDensity object.
107
108        Args:
109            edos: Electron density of states.
110            fermi_lv: Fermi level [$\mathrm{eV}$].
111            temperature: Temperature [$\mathrm{K}$].
112
113        Raises:
114            TypeError: If `edos` is not a ElectronDensityOfStates object.
115            ValueError: If temperature is non-positive.
116        """
117        if not isinstance(edos, ElectronDensityOfStates):
118            raise TypeError("Not a ElectronDensityOfStates object!")
119        if temperature <= 0.0:
120            raise ValueError("Non-positive temperature!")
121
122        self._edos = edos
123        self._fermi_lv = float(fermi_lv)
124        self._temperature = float(temperature)
125        self._energies = edos.energies
126
127        if isinstance(self, SpectralElectronDensity):
128            occups = ret_fd_occups(
129                self.energies,
130                fermi_lv=self.fermi_lv,
131                temperature=self.temperature,
132            )
133        elif isinstance(self, SpectralHoleDensity):
134            occups = 1.0 - ret_fd_occups(
135                self.energies,
136                fermi_lv=self.fermi_lv,
137                temperature=self.temperature,
138            )
139        else:
140            occups = 1.0
141
142        self._values = occups * edos.values
143        self._integr = np.trapz(self._values, x=self._energies)
144        self._sp_eden = None
145        self._sp_hden = None
146
147    def __add__(self, other: Self) -> Self:
148        r"""Add spectral carrier density.
149
150        Args:
151            other: Spectral carrier density to add.
152
153        Returns:
154            Sum of `self` and `other`.
155
156        Raises:
157            TypeError: If `self` and `other` have incompatible types.
158            ValueError: If `self` and `other`have incompatible Fermi levels.
159            ValueError: If `self` and `other`have incompatible temperatures.
160        """
161        if type(self) != type(other):
162            raise TypeError("Incompatible types!")
163        if self.fermi_lv != other.fermi_lv:
164            raise ValueError("Incompatible Fermi levels!")
165        if self.temperature != other.temperature:
166            raise ValueError("Incompatible temperatures!")
167        edos = self.edos + other.edos
168        return type(self)(
169            edos, fermi_lv=self.fermi_lv, temperature=self.temperature
170        )
171
172    @property
173    def edos(self) -> ElectronDensityOfStates:
174        r"""Electron density of states."""
175        return self._edos
176
177    @property
178    def fermi_lv(self) -> float:
179        r"""Fermi level [$\mathrm{eV}$]."""
180        return self._fermi_lv
181
182    @property
183    def temperature(self) -> float:
184        r"""Temperature [$\mathrm{K}$]."""
185        return self._temperature
186
187    @property
188    def sp_eden(self) -> SpectralElectronDensity:
189        r"""Spectral electron density."""
190        if self._sp_eden is None:
191            if isinstance(self, SpectralElectronDensity):
192                self._sp_eden = self
193            else:
194                self._sp_eden = SpectralElectronDensity(
195                    self.edos,
196                    fermi_lv=self.fermi_lv,
197                    temperature=self.temperature,
198                )
199        return self._sp_eden
200
201    @property
202    def sp_hden(self) -> SpectralHoleDensity:
203        r"""Spectral hole density."""
204        if self._sp_hden is None:
205            if isinstance(self, SpectralHoleDensity):
206                self._sp_hden = self
207            else:
208                self._sp_hden = SpectralHoleDensity(
209                    self.edos,
210                    fermi_lv=self.fermi_lv,
211                    temperature=self.temperature,
212                )
213        return self._sp_hden
214
215    def ret_zero(self) -> Self:
216        r"""Return zero spectral carrier density."""
217        return type(self).zero(
218            self.energies, fermi_lv=self.fermi_lv, temperature=self.temperature
219        )
220
221    def ret_smeared(self, *, sigma: Real) -> Self:
222        r"""Return smeared spectral carrier density.
223
224        Args:
225            sigma: Standard deviation for Gaussian kernel.
226
227        Returns:
228            Smeared spectral carrier density.
229        """
230        edos = self.edos.ret_smeared(sigma=sigma)
231        return type(self)(
232            edos, fermi_lv=self.fermi_lv, temperature=self.temperature
233        )
234
235    def ret_band_rsv(
236        self, *, threshold: Real = 0.0
237    ) -> BandResolvedSpectralCarrierDensity:
238        r"""Return band resolved spectral carrier density.
239
240        Args:
241            threshold: Threshold below which electron density of states values
242                are rounded to zero [$\mathrm{eV^{-1}}$].
243
244        Returns:
245            Band resolved spectral carrier density.
246        """
247        rsv_edos = self.edos.ret_band_rsv(threshold=threshold)
248        return type(self).band_rsv(
249            rsv_edos, fermi_lv=self.fermi_lv, temperature=self.temperature
250        )
251
252    def calc_ejdos(self) -> ElectronJointDensityOfStates:
253        r"""Calculate electron joint density of states.
254
255        Returns:
256            Electron joint density of states.
257        """
258        ejdos_energies, ejdos_values = correlate1d(
259            self.energies, self.sp_eden.values, self.sp_hden.values
260        )
261        return ElectronJointDensityOfStates(ejdos_energies, ejdos_values)
262
263    def plot_fermi_lv(
264        self,
265        *,
266        ax: plt.Axes,
267        color: str | None = None,
268        label: str | None = None,
269    ) -> plt.Figure:
270        r"""Plot Fermi level.
271
272        Args:
273            ax: Plot axes; if None, new figure and axes are created.
274            color: Line color.
275            label: Line label.
276
277        Returns:
278            Plot figure.
279        """
280        ax.axvline(self.fermi_lv, linestyle="--", color=color, label=label)
281        return ax.get_figure()
282
283    @classmethod
284    def zero(
285        cls,
286        energies: Sequence[Real, ...],
287        *,
288        d_energy: Real | None = None,
289        fermi_lv: Real = 0.0,
290        temperature: Real = 300.0,
291    ) -> np.ndarray[float]:
292        r"""Zero spectral carrier density.
293
294        Args:
295            energies: Electron energies [$\mathrm{eV}$].
296            d_energy: Target electron energy increment [$\mathrm{eV}$].
297            fermi_lv: Fermi level [$\mathrm{eV}$].
298            temperature: Temperature [$\mathrm{K}$].
299
300        Returns:
301            Zero spectral carrier density.
302        """
303        edos = ElectronDensityOfStates.zero(energies, d_energy=d_energy)
304        return cls(edos, fermi_lv=fermi_lv, temperature=temperature)
305
306    @classmethod
307    def piecewise_constant(
308        cls,
309        energy_a: Real,
310        energy_b: Real,
311        d_energy: Real,
312        *,
313        amplitudes: Sequence[Real, ...],
314        low_bounds: Sequence[Real, ...],
315        upp_bounds: Sequence[Real, ...],
316        fermi_lv: Real = 0.0,
317        temperature: Real = 300.0,
318    ) -> Self:
319        r"""Piecewise constant spectral carrier density.
320
321        Args:
322            energy_a: Electron energy minimum [$\mathrm{eV}$].
323            energy_b: Electron energy maximum [$\mathrm{eV}$].
324            d_energy: Target electron energy increment [$\mathrm{eV}$].
325            amplitudes: Electron density of states piece amplitudes
326                [$\mathrm{eV^{-1}}$].
327            low_bounds: Electron density of states piece lower bounds
328                [$\mathrm{eV}$].
329            upp_bounds: Electron density of states piece upper bounds
330                [$\mathrm{eV}$].
331            fermi_lv: Fermi level [$\mathrm{eV}$].
332            temperature: Temperature [$\mathrm{K}$].
333
334        Returns:
335            Piecewise constant spectral carrier density.
336        """
337        edos = ElectronDensityOfStates.piecewise_constant(
338            energy_a,
339            energy_b,
340            d_energy,
341            amplitudes=amplitudes,
342            low_bounds=low_bounds,
343            upp_bounds=upp_bounds,
344        )
345        return cls(edos, fermi_lv=fermi_lv, temperature=temperature)

Spectral carrier density.

Note:

energies: Electron energies [$\mathrm{eV}$]. values: Spectral carrier density values [$\mathrm{eV^{-1}}$].

SpectralCarrierDensity( edos: madman.analysis.edos.ElectronDensityOfStates, *, fermi_lv: numbers.Real = 0.0, temperature: numbers.Real = 300.0)
 99    def __init__(
100        self,
101        edos: ElectronDensityOfStates,
102        *,
103        fermi_lv: Real = 0.0,
104        temperature: Real = 300.0,
105    ) -> None:
106        r"""Initialize SpectralCarrierDensity object.
107
108        Args:
109            edos: Electron density of states.
110            fermi_lv: Fermi level [$\mathrm{eV}$].
111            temperature: Temperature [$\mathrm{K}$].
112
113        Raises:
114            TypeError: If `edos` is not a ElectronDensityOfStates object.
115            ValueError: If temperature is non-positive.
116        """
117        if not isinstance(edos, ElectronDensityOfStates):
118            raise TypeError("Not a ElectronDensityOfStates object!")
119        if temperature <= 0.0:
120            raise ValueError("Non-positive temperature!")
121
122        self._edos = edos
123        self._fermi_lv = float(fermi_lv)
124        self._temperature = float(temperature)
125        self._energies = edos.energies
126
127        if isinstance(self, SpectralElectronDensity):
128            occups = ret_fd_occups(
129                self.energies,
130                fermi_lv=self.fermi_lv,
131                temperature=self.temperature,
132            )
133        elif isinstance(self, SpectralHoleDensity):
134            occups = 1.0 - ret_fd_occups(
135                self.energies,
136                fermi_lv=self.fermi_lv,
137                temperature=self.temperature,
138            )
139        else:
140            occups = 1.0
141
142        self._values = occups * edos.values
143        self._integr = np.trapz(self._values, x=self._energies)
144        self._sp_eden = None
145        self._sp_hden = None

Initialize SpectralCarrierDensity object.

Arguments:
  • edos: Electron density of states.
  • fermi_lv: Fermi level [$\mathrm{eV}$].
  • temperature: Temperature [$\mathrm{K}$].
Raises:
  • TypeError: If edos is not a ElectronDensityOfStates object.
  • ValueError: If temperature is non-positive.
172    @property
173    def edos(self) -> ElectronDensityOfStates:
174        r"""Electron density of states."""
175        return self._edos

Electron density of states.

fermi_lv: float
177    @property
178    def fermi_lv(self) -> float:
179        r"""Fermi level [$\mathrm{eV}$]."""
180        return self._fermi_lv

Fermi level [$\mathrm{eV}$].

temperature: float
182    @property
183    def temperature(self) -> float:
184        r"""Temperature [$\mathrm{K}$]."""
185        return self._temperature

Temperature [$\mathrm{K}$].

sp_eden: SpectralElectronDensity
187    @property
188    def sp_eden(self) -> SpectralElectronDensity:
189        r"""Spectral electron density."""
190        if self._sp_eden is None:
191            if isinstance(self, SpectralElectronDensity):
192                self._sp_eden = self
193            else:
194                self._sp_eden = SpectralElectronDensity(
195                    self.edos,
196                    fermi_lv=self.fermi_lv,
197                    temperature=self.temperature,
198                )
199        return self._sp_eden

Spectral electron density.

sp_hden: SpectralHoleDensity
201    @property
202    def sp_hden(self) -> SpectralHoleDensity:
203        r"""Spectral hole density."""
204        if self._sp_hden is None:
205            if isinstance(self, SpectralHoleDensity):
206                self._sp_hden = self
207            else:
208                self._sp_hden = SpectralHoleDensity(
209                    self.edos,
210                    fermi_lv=self.fermi_lv,
211                    temperature=self.temperature,
212                )
213        return self._sp_hden

Spectral hole density.

def ret_zero(self) -> Self:
215    def ret_zero(self) -> Self:
216        r"""Return zero spectral carrier density."""
217        return type(self).zero(
218            self.energies, fermi_lv=self.fermi_lv, temperature=self.temperature
219        )

Return zero spectral carrier density.

def ret_smeared(self, *, sigma: numbers.Real) -> Self:
221    def ret_smeared(self, *, sigma: Real) -> Self:
222        r"""Return smeared spectral carrier density.
223
224        Args:
225            sigma: Standard deviation for Gaussian kernel.
226
227        Returns:
228            Smeared spectral carrier density.
229        """
230        edos = self.edos.ret_smeared(sigma=sigma)
231        return type(self)(
232            edos, fermi_lv=self.fermi_lv, temperature=self.temperature
233        )

Return smeared spectral carrier density.

Arguments:
  • sigma: Standard deviation for Gaussian kernel.
Returns:

Smeared spectral carrier density.

def ret_band_rsv( self, *, threshold: numbers.Real = 0.0) -> BandResolvedSpectralCarrierDensity:
235    def ret_band_rsv(
236        self, *, threshold: Real = 0.0
237    ) -> BandResolvedSpectralCarrierDensity:
238        r"""Return band resolved spectral carrier density.
239
240        Args:
241            threshold: Threshold below which electron density of states values
242                are rounded to zero [$\mathrm{eV^{-1}}$].
243
244        Returns:
245            Band resolved spectral carrier density.
246        """
247        rsv_edos = self.edos.ret_band_rsv(threshold=threshold)
248        return type(self).band_rsv(
249            rsv_edos, fermi_lv=self.fermi_lv, temperature=self.temperature
250        )

Return band resolved spectral carrier density.

Arguments:
  • threshold: Threshold below which electron density of states values are rounded to zero [$\mathrm{eV^{-1}}$].
Returns:

Band resolved spectral carrier density.

def calc_ejdos(self) -> madman.analysis.ejdos.ElectronJointDensityOfStates:
252    def calc_ejdos(self) -> ElectronJointDensityOfStates:
253        r"""Calculate electron joint density of states.
254
255        Returns:
256            Electron joint density of states.
257        """
258        ejdos_energies, ejdos_values = correlate1d(
259            self.energies, self.sp_eden.values, self.sp_hden.values
260        )
261        return ElectronJointDensityOfStates(ejdos_energies, ejdos_values)

Calculate electron joint density of states.

Returns:

Electron joint density of states.

def plot_fermi_lv( self, *, ax: matplotlib.axes._axes.Axes, color: str | None = None, label: str | None = None) -> matplotlib.figure.Figure:
263    def plot_fermi_lv(
264        self,
265        *,
266        ax: plt.Axes,
267        color: str | None = None,
268        label: str | None = None,
269    ) -> plt.Figure:
270        r"""Plot Fermi level.
271
272        Args:
273            ax: Plot axes; if None, new figure and axes are created.
274            color: Line color.
275            label: Line label.
276
277        Returns:
278            Plot figure.
279        """
280        ax.axvline(self.fermi_lv, linestyle="--", color=color, label=label)
281        return ax.get_figure()

Plot Fermi level.

Arguments:
  • ax: Plot axes; if None, new figure and axes are created.
  • color: Line color.
  • label: Line label.
Returns:

Plot figure.

@classmethod
def zero( cls, energies: collections.abc.Sequence[numbers.Real, ...], *, d_energy: numbers.Real | None = None, fermi_lv: numbers.Real = 0.0, temperature: numbers.Real = 300.0) -> numpy.ndarray[float]:
283    @classmethod
284    def zero(
285        cls,
286        energies: Sequence[Real, ...],
287        *,
288        d_energy: Real | None = None,
289        fermi_lv: Real = 0.0,
290        temperature: Real = 300.0,
291    ) -> np.ndarray[float]:
292        r"""Zero spectral carrier density.
293
294        Args:
295            energies: Electron energies [$\mathrm{eV}$].
296            d_energy: Target electron energy increment [$\mathrm{eV}$].
297            fermi_lv: Fermi level [$\mathrm{eV}$].
298            temperature: Temperature [$\mathrm{K}$].
299
300        Returns:
301            Zero spectral carrier density.
302        """
303        edos = ElectronDensityOfStates.zero(energies, d_energy=d_energy)
304        return cls(edos, fermi_lv=fermi_lv, temperature=temperature)

Zero spectral carrier density.

Arguments:
  • energies: Electron energies [$\mathrm{eV}$].
  • d_energy: Target electron energy increment [$\mathrm{eV}$].
  • fermi_lv: Fermi level [$\mathrm{eV}$].
  • temperature: Temperature [$\mathrm{K}$].
Returns:

Zero spectral carrier density.

@classmethod
def piecewise_constant( cls, energy_a: numbers.Real, energy_b: numbers.Real, d_energy: numbers.Real, *, amplitudes: collections.abc.Sequence[numbers.Real, ...], low_bounds: collections.abc.Sequence[numbers.Real, ...], upp_bounds: collections.abc.Sequence[numbers.Real, ...], fermi_lv: numbers.Real = 0.0, temperature: numbers.Real = 300.0) -> Self:
306    @classmethod
307    def piecewise_constant(
308        cls,
309        energy_a: Real,
310        energy_b: Real,
311        d_energy: Real,
312        *,
313        amplitudes: Sequence[Real, ...],
314        low_bounds: Sequence[Real, ...],
315        upp_bounds: Sequence[Real, ...],
316        fermi_lv: Real = 0.0,
317        temperature: Real = 300.0,
318    ) -> Self:
319        r"""Piecewise constant spectral carrier density.
320
321        Args:
322            energy_a: Electron energy minimum [$\mathrm{eV}$].
323            energy_b: Electron energy maximum [$\mathrm{eV}$].
324            d_energy: Target electron energy increment [$\mathrm{eV}$].
325            amplitudes: Electron density of states piece amplitudes
326                [$\mathrm{eV^{-1}}$].
327            low_bounds: Electron density of states piece lower bounds
328                [$\mathrm{eV}$].
329            upp_bounds: Electron density of states piece upper bounds
330                [$\mathrm{eV}$].
331            fermi_lv: Fermi level [$\mathrm{eV}$].
332            temperature: Temperature [$\mathrm{K}$].
333
334        Returns:
335            Piecewise constant spectral carrier density.
336        """
337        edos = ElectronDensityOfStates.piecewise_constant(
338            energy_a,
339            energy_b,
340            d_energy,
341            amplitudes=amplitudes,
342            low_bounds=low_bounds,
343            upp_bounds=upp_bounds,
344        )
345        return cls(edos, fermi_lv=fermi_lv, temperature=temperature)

Piecewise constant spectral carrier density.

Arguments:
  • energy_a: Electron energy minimum [$\mathrm{eV}$].
  • energy_b: Electron energy maximum [$\mathrm{eV}$].
  • d_energy: Target electron energy increment [$\mathrm{eV}$].
  • amplitudes: Electron density of states piece amplitudes [$\mathrm{eV^{-1}}$].
  • low_bounds: Electron density of states piece lower bounds [$\mathrm{eV}$].
  • upp_bounds: Electron density of states piece upper bounds [$\mathrm{eV}$].
  • fermi_lv: Fermi level [$\mathrm{eV}$].
  • temperature: Temperature [$\mathrm{K}$].
Returns:

Piecewise constant spectral carrier density.

class SpectralElectronDensity(SpectralCarrierDensity):
348class SpectralElectronDensity(SpectralCarrierDensity):
349    r"""Spectral electron density.
350
351    Note:
352        `energies`: Electron energies [$\mathrm{eV}$].
353        `values`: Spectral electron density values [$\mathrm{eV^{-1}}$].
354    """

Spectral electron density.

Note:

energies: Electron energies [$\mathrm{eV}$]. values: Spectral electron density values [$\mathrm{eV^{-1}}$].

class SpectralHoleDensity(SpectralCarrierDensity):
357class SpectralHoleDensity(SpectralCarrierDensity):
358    r"""Spectral hole density.
359
360    Note:
361        `energies`: Electron energies [$\mathrm{eV}$].
362        `values`: Spectral hole density values [$\mathrm{eV^{-1}}$].
363    """

Spectral hole density.

Note:

energies: Electron energies [$\mathrm{eV}$]. values: Spectral hole density values [$\mathrm{eV^{-1}}$].

class ResolvedSpectralCarrierDensityMeta(madman.analysis.spectrum.ResolvedEnergySpectrumMeta):
366class ResolvedSpectralCarrierDensityMeta(ResolvedEnergySpectrumMeta):
367    r"""Metaclass of ResolvedSpectralCarrierDensity."""
368
369    @property
370    def rsv_edos(cls) -> Type:
371        r"""Associated resolved electron density of states class."""
372        module = modules[cls.__module__]
373        name = (
374            cls.__name__[: cls.__name__.index("Resolved") + len("Resolved")]
375            + "ElectronDensityOfStates"
376        )
377        return getattr(module, name)
378
379    @property
380    def rsv_sp_eden(cls) -> Type:
381        r"""Associated resolved spectral electron density class."""
382        module = modules[cls.__module__]
383        name = cls.__name__.replace("Carrier", "Electron").replace(
384            "Hole", "Electron"
385        )
386        return getattr(module, name)
387
388    @property
389    def rsv_sp_hden(cls) -> Type:
390        r"""Associated resolved spectral hole density class."""
391        module = modules[cls.__module__]
392        name = cls.__name__.replace("Carrier", "Hole").replace(
393            "Electron", "Hole"
394        )
395        return getattr(module, name)
396
397    @property
398    def rsv_ejdos(cls) -> Type:
399        r"""Associated resolved electron joint density of states class."""
400        module = modules[cls.__module__]
401        name = (
402            cls.__name__[: cls.__name__.index("Resolved") + len("Resolved")]
403            + "ElectronJointDensityOfStates"
404        )
405        return getattr(module, name)

Metaclass of ResolvedSpectralCarrierDensity.

rsv_edos: Type
369    @property
370    def rsv_edos(cls) -> Type:
371        r"""Associated resolved electron density of states class."""
372        module = modules[cls.__module__]
373        name = (
374            cls.__name__[: cls.__name__.index("Resolved") + len("Resolved")]
375            + "ElectronDensityOfStates"
376        )
377        return getattr(module, name)

Associated resolved electron density of states class.

rsv_sp_eden: Type
379    @property
380    def rsv_sp_eden(cls) -> Type:
381        r"""Associated resolved spectral electron density class."""
382        module = modules[cls.__module__]
383        name = cls.__name__.replace("Carrier", "Electron").replace(
384            "Hole", "Electron"
385        )
386        return getattr(module, name)

Associated resolved spectral electron density class.

rsv_sp_hden: Type
388    @property
389    def rsv_sp_hden(cls) -> Type:
390        r"""Associated resolved spectral hole density class."""
391        module = modules[cls.__module__]
392        name = cls.__name__.replace("Carrier", "Hole").replace(
393            "Electron", "Hole"
394        )
395        return getattr(module, name)

Associated resolved spectral hole density class.

rsv_ejdos: Type
397    @property
398    def rsv_ejdos(cls) -> Type:
399        r"""Associated resolved electron joint density of states class."""
400        module = modules[cls.__module__]
401        name = (
402            cls.__name__[: cls.__name__.index("Resolved") + len("Resolved")]
403            + "ElectronJointDensityOfStates"
404        )
405        return getattr(module, name)

Associated resolved electron joint density of states class.

Inherited Members
builtins.type
type
mro
madman.analysis.spectrum.ResolvedEnergySpectrumMeta
total
class ResolvedSpectralCarrierDensity(madman.analysis.spectrum.ResolvedEnergySpectrum):
408class ResolvedSpectralCarrierDensity(
409    ResolvedEnergySpectrum, metaclass=ResolvedSpectralCarrierDensityMeta
410):
411    r"""Resolved spectral carrier density.
412
413    Note:
414        `energies`: Electron energies [$\mathrm{eV}$].
415        `rsv_values`: Resolved spectral carrier density values
416            [$\mathrm{eV^{-1}}$].
417    """
418
419    def __init__(
420        self,
421        rsv_edos: ResolvedElectronDensityOfStates,
422        *,
423        fermi_lv: Real = 0.0,
424        temperature: Real = 300.0,
425    ) -> None:
426        r"""Initialize ResolvedSpectralCarrierDensity object.
427
428        Args:
429            rsv_edos: Resolved electron density of states.
430            fermi_lv: Fermi level [$\mathrm{eV}$].
431            temperature: Temperature [$\mathrm{K}$].
432
433        Raises:
434            TypeError: If resolved electron density of states is incompatible.
435            ValueError: If temperature is non-positive.
436        """
437        if type(rsv_edos) != type(self).rsv_edos:
438            raise TypeError("Incompatible resolved electron density of states!")
439        if temperature <= 0.0:
440            raise ValueError("Non-positive temperature!")
441
442        self._rsv_edos = rsv_edos
443        self._fermi_lv = float(fermi_lv)
444        self._temperature = float(temperature)
445        self._energies = self.rsv_edos.energies
446
447        if isinstance(self, ResolvedSpectralElectronDensity):
448            occups = ret_fd_occups(
449                self.energies,
450                fermi_lv=self.fermi_lv,
451                temperature=self.temperature,
452            )
453        elif isinstance(self, ResolvedSpectralHoleDensity):
454            occups = 1.0 - ret_fd_occups(
455                self.energies,
456                fermi_lv=self.fermi_lv,
457                temperature=self.temperature,
458            )
459        else:
460            occups = 1.0
461
462        self._rsv_values = {
463            feat: occups * edos_values
464            for feat, edos_values in self.rsv_edos.rsv_values.items()
465        }
466        self._rsv_integr = {
467            feat: np.trapz(values, x=self.energies)
468            for feat, values in self._rsv_values.items()
469        }
470        self._total = type(self).total(
471            self.rsv_edos.total,
472            fermi_lv=self.fermi_lv,
473            temperature=self.temperature,
474        )
475        self._rsv_sp_eden = None
476        self._rsv_sp_hden = None
477
478    @property
479    def rsv_edos(self) -> ResolvedElectronDensityOfStates:
480        r"""Resolved electron density of states."""
481        return self._rsv_edos
482
483    @property
484    def fermi_lv(self) -> float:
485        r"""Fermi level [$\mathrm{eV}$]."""
486        return self._fermi_lv
487
488    @property
489    def temperature(self) -> float:
490        r"""Temperature [$\mathrm{K}$]."""
491        return self._temperature
492
493    @property
494    def rsv_sp_eden(self) -> ResolvedSpectralElectronDensity:
495        r"""Resolved spectral electron density."""
496        if self._rsv_sp_eden is None:
497            if isinstance(self, ResolvedSpectralElectronDensity):
498                self._rsv_sp_eden = self
499            else:
500                self._rsv_sp_eden = type(self).rsv_sp_eden(
501                    self.rsv_edos,
502                    fermi_lv=self.fermi_lv,
503                    temperature=self.temperature,
504                )
505        return self._rsv_sp_eden
506
507    @property
508    def rsv_sp_hden(self) -> ResolvedSpectralHoleDensity:
509        r"""Resolved spectral hole density."""
510        if self._rsv_sp_hden is None:
511            if isinstance(self, ResolvedSpectralHoleDensity):
512                self._rsv_sp_hden = self
513            else:
514                self._rsv_sp_hden = type(self).rsv_sp_hden(
515                    self.rsv_edos,
516                    fermi_lv=self.fermi_lv,
517                    temperature=self.temperature,
518                )
519        return self._rsv_sp_hden
520
521    def ret_zero(self) -> Self:
522        r"""Return zero resolved spectral carrier density."""
523        return type(self).zero(
524            self.rsv_edos.energies,
525            self.rsv_edos.rsv_values.keys(),
526            fermi_lv=self.fermi_lv,
527            temperature=self.temperature,
528        )
529
530    def ret_smeared(self, *, sigma: Real) -> Self:
531        r"""Return smeared resolved spectral carrier density.
532
533        Args:
534            sigma: Standard deviation for Gaussian kernel.
535
536        Returns:
537            Smeared resolved spectral carrier density.
538        """
539        rsv_edos = self.rsv_edos.ret_smeared(sigma=sigma)
540        return type(self)(
541            rsv_edos, fermi_lv=self.fermi_lv, temperature=self.temperature
542        )
543
544    def calc_rsv_ejdos(self) -> ResolvedElectronJointDensityOfStates:
545        r"""Calculate resolved electron joint density of states."""
546        rsv_ejdos_values = {}
547        for feat_e, values_e in self.rsv_sp_eden.rsv_values.items():
548            for feat_h, values_h in self.rsv_sp_hden.rsv_values.items():
549                if isinstance(self, CellResolvedSpectralCarrierDensity):
550                    pair = feat_e + feat_h
551                    if pair not in {"ii", "vi", "ic", "vc"}:
552                        continue
553                else:
554                    pair = (feat_e, feat_h)
555
556                ejdos_energies, ejdos_values = correlate1d(
557                    self.energies, values_e, values_h
558                )
559                rsv_ejdos_values[pair] = ejdos_values
560
561        return type(self).rsv_ejdos(ejdos_energies, rsv_ejdos_values)
562
563    def plot_fermi_lv(
564        self,
565        *,
566        ax: plt.Axes,
567        color: str | None = None,
568        label: str | None = None,
569    ) -> plt.Figure:
570        r"""Plot Fermi level.
571
572        Args:
573            ax: Plot axes; if None, new figure and axes are created.
574            color: Line color.
575            label: Line label.
576
577        Returns:
578            Plot figure.
579        """
580        ax.axvline(self.fermi_lv, linestyle="--", color=color, label=label)
581        return ax.get_figure()
582
583    @classmethod
584    def zero(
585        cls,
586        energies: Sequence[Real, ...],
587        features: Sequence[Any, ...],
588        *,
589        d_energy: Real | None = None,
590        fermi_lv: Real = 0.0,
591        temperature: Real = 300.0,
592    ) -> Self:
593        r"""Zero resolved spectral carrier density.
594
595        Args:
596            energies: Resolved spectral carrier density energies
597                [$\mathrm{eV}$].
598            features: Resolved spectral carrier density features.
599            d_energy: Target electron energy increment [$\mathrm{eV}$].
600            fermi_lv: Fermi level [$\mathrm{eV}$].
601            temperature: Temperature [$\mathrm{K}$].
602
603        Returns:
604            Zero resolved spectral carrier density.
605        """
606        rsv_edos = cls.rsv_edos.zero(energies, features, d_energy=d_energy)
607        return cls(rsv_edos, fermi_lv=fermi_lv, temperature=temperature)

Resolved spectral carrier density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Resolved spectral carrier density values [$\mathrm{eV^{-1}}$].

ResolvedSpectralCarrierDensity( rsv_edos: madman.analysis.edos.ResolvedElectronDensityOfStates, *, fermi_lv: numbers.Real = 0.0, temperature: numbers.Real = 300.0)
419    def __init__(
420        self,
421        rsv_edos: ResolvedElectronDensityOfStates,
422        *,
423        fermi_lv: Real = 0.0,
424        temperature: Real = 300.0,
425    ) -> None:
426        r"""Initialize ResolvedSpectralCarrierDensity object.
427
428        Args:
429            rsv_edos: Resolved electron density of states.
430            fermi_lv: Fermi level [$\mathrm{eV}$].
431            temperature: Temperature [$\mathrm{K}$].
432
433        Raises:
434            TypeError: If resolved electron density of states is incompatible.
435            ValueError: If temperature is non-positive.
436        """
437        if type(rsv_edos) != type(self).rsv_edos:
438            raise TypeError("Incompatible resolved electron density of states!")
439        if temperature <= 0.0:
440            raise ValueError("Non-positive temperature!")
441
442        self._rsv_edos = rsv_edos
443        self._fermi_lv = float(fermi_lv)
444        self._temperature = float(temperature)
445        self._energies = self.rsv_edos.energies
446
447        if isinstance(self, ResolvedSpectralElectronDensity):
448            occups = ret_fd_occups(
449                self.energies,
450                fermi_lv=self.fermi_lv,
451                temperature=self.temperature,
452            )
453        elif isinstance(self, ResolvedSpectralHoleDensity):
454            occups = 1.0 - ret_fd_occups(
455                self.energies,
456                fermi_lv=self.fermi_lv,
457                temperature=self.temperature,
458            )
459        else:
460            occups = 1.0
461
462        self._rsv_values = {
463            feat: occups * edos_values
464            for feat, edos_values in self.rsv_edos.rsv_values.items()
465        }
466        self._rsv_integr = {
467            feat: np.trapz(values, x=self.energies)
468            for feat, values in self._rsv_values.items()
469        }
470        self._total = type(self).total(
471            self.rsv_edos.total,
472            fermi_lv=self.fermi_lv,
473            temperature=self.temperature,
474        )
475        self._rsv_sp_eden = None
476        self._rsv_sp_hden = None

Initialize ResolvedSpectralCarrierDensity object.

Arguments:
  • rsv_edos: Resolved electron density of states.
  • fermi_lv: Fermi level [$\mathrm{eV}$].
  • temperature: Temperature [$\mathrm{K}$].
Raises:
  • TypeError: If resolved electron density of states is incompatible.
  • ValueError: If temperature is non-positive.
478    @property
479    def rsv_edos(self) -> ResolvedElectronDensityOfStates:
480        r"""Resolved electron density of states."""
481        return self._rsv_edos

Resolved electron density of states.

fermi_lv: float
483    @property
484    def fermi_lv(self) -> float:
485        r"""Fermi level [$\mathrm{eV}$]."""
486        return self._fermi_lv

Fermi level [$\mathrm{eV}$].

temperature: float
488    @property
489    def temperature(self) -> float:
490        r"""Temperature [$\mathrm{K}$]."""
491        return self._temperature

Temperature [$\mathrm{K}$].

rsv_sp_eden: ResolvedSpectralElectronDensity
493    @property
494    def rsv_sp_eden(self) -> ResolvedSpectralElectronDensity:
495        r"""Resolved spectral electron density."""
496        if self._rsv_sp_eden is None:
497            if isinstance(self, ResolvedSpectralElectronDensity):
498                self._rsv_sp_eden = self
499            else:
500                self._rsv_sp_eden = type(self).rsv_sp_eden(
501                    self.rsv_edos,
502                    fermi_lv=self.fermi_lv,
503                    temperature=self.temperature,
504                )
505        return self._rsv_sp_eden

Resolved spectral electron density.

rsv_sp_hden: ResolvedSpectralHoleDensity
507    @property
508    def rsv_sp_hden(self) -> ResolvedSpectralHoleDensity:
509        r"""Resolved spectral hole density."""
510        if self._rsv_sp_hden is None:
511            if isinstance(self, ResolvedSpectralHoleDensity):
512                self._rsv_sp_hden = self
513            else:
514                self._rsv_sp_hden = type(self).rsv_sp_hden(
515                    self.rsv_edos,
516                    fermi_lv=self.fermi_lv,
517                    temperature=self.temperature,
518                )
519        return self._rsv_sp_hden

Resolved spectral hole density.

def ret_zero(self) -> Self:
521    def ret_zero(self) -> Self:
522        r"""Return zero resolved spectral carrier density."""
523        return type(self).zero(
524            self.rsv_edos.energies,
525            self.rsv_edos.rsv_values.keys(),
526            fermi_lv=self.fermi_lv,
527            temperature=self.temperature,
528        )

Return zero resolved spectral carrier density.

def ret_smeared(self, *, sigma: numbers.Real) -> Self:
530    def ret_smeared(self, *, sigma: Real) -> Self:
531        r"""Return smeared resolved spectral carrier density.
532
533        Args:
534            sigma: Standard deviation for Gaussian kernel.
535
536        Returns:
537            Smeared resolved spectral carrier density.
538        """
539        rsv_edos = self.rsv_edos.ret_smeared(sigma=sigma)
540        return type(self)(
541            rsv_edos, fermi_lv=self.fermi_lv, temperature=self.temperature
542        )

Return smeared resolved spectral carrier density.

Arguments:
  • sigma: Standard deviation for Gaussian kernel.
Returns:

Smeared resolved spectral carrier density.

def calc_rsv_ejdos(self) -> madman.analysis.ejdos.ResolvedElectronJointDensityOfStates:
544    def calc_rsv_ejdos(self) -> ResolvedElectronJointDensityOfStates:
545        r"""Calculate resolved electron joint density of states."""
546        rsv_ejdos_values = {}
547        for feat_e, values_e in self.rsv_sp_eden.rsv_values.items():
548            for feat_h, values_h in self.rsv_sp_hden.rsv_values.items():
549                if isinstance(self, CellResolvedSpectralCarrierDensity):
550                    pair = feat_e + feat_h
551                    if pair not in {"ii", "vi", "ic", "vc"}:
552                        continue
553                else:
554                    pair = (feat_e, feat_h)
555
556                ejdos_energies, ejdos_values = correlate1d(
557                    self.energies, values_e, values_h
558                )
559                rsv_ejdos_values[pair] = ejdos_values
560
561        return type(self).rsv_ejdos(ejdos_energies, rsv_ejdos_values)

Calculate resolved electron joint density of states.

def plot_fermi_lv( self, *, ax: matplotlib.axes._axes.Axes, color: str | None = None, label: str | None = None) -> matplotlib.figure.Figure:
563    def plot_fermi_lv(
564        self,
565        *,
566        ax: plt.Axes,
567        color: str | None = None,
568        label: str | None = None,
569    ) -> plt.Figure:
570        r"""Plot Fermi level.
571
572        Args:
573            ax: Plot axes; if None, new figure and axes are created.
574            color: Line color.
575            label: Line label.
576
577        Returns:
578            Plot figure.
579        """
580        ax.axvline(self.fermi_lv, linestyle="--", color=color, label=label)
581        return ax.get_figure()

Plot Fermi level.

Arguments:
  • ax: Plot axes; if None, new figure and axes are created.
  • color: Line color.
  • label: Line label.
Returns:

Plot figure.

@classmethod
def zero( cls, energies: collections.abc.Sequence[numbers.Real, ...], features: collections.abc.Sequence[typing.Any, ...], *, d_energy: numbers.Real | None = None, fermi_lv: numbers.Real = 0.0, temperature: numbers.Real = 300.0) -> Self:
583    @classmethod
584    def zero(
585        cls,
586        energies: Sequence[Real, ...],
587        features: Sequence[Any, ...],
588        *,
589        d_energy: Real | None = None,
590        fermi_lv: Real = 0.0,
591        temperature: Real = 300.0,
592    ) -> Self:
593        r"""Zero resolved spectral carrier density.
594
595        Args:
596            energies: Resolved spectral carrier density energies
597                [$\mathrm{eV}$].
598            features: Resolved spectral carrier density features.
599            d_energy: Target electron energy increment [$\mathrm{eV}$].
600            fermi_lv: Fermi level [$\mathrm{eV}$].
601            temperature: Temperature [$\mathrm{K}$].
602
603        Returns:
604            Zero resolved spectral carrier density.
605        """
606        rsv_edos = cls.rsv_edos.zero(energies, features, d_energy=d_energy)
607        return cls(rsv_edos, fermi_lv=fermi_lv, temperature=temperature)

Zero resolved spectral carrier density.

Arguments:
  • energies: Resolved spectral carrier density energies [$\mathrm{eV}$].
  • features: Resolved spectral carrier density features.
  • d_energy: Target electron energy increment [$\mathrm{eV}$].
  • fermi_lv: Fermi level [$\mathrm{eV}$].
  • temperature: Temperature [$\mathrm{K}$].
Returns:

Zero resolved spectral carrier density.

class ResolvedSpectralElectronDensity(ResolvedSpectralCarrierDensity):
610class ResolvedSpectralElectronDensity(ResolvedSpectralCarrierDensity):
611    r"""Resolved spectral electron density.
612
613    Note:
614        `energies`: Electron energies [$\mathrm{eV}$].
615        `rsv_values`: Resolved spectral electron density values
616            [$\mathrm{eV^{-1}}$].
617    """

Resolved spectral electron density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Resolved spectral electron density values [$\mathrm{eV^{-1}}$].

class ResolvedSpectralHoleDensity(ResolvedSpectralCarrierDensity):
620class ResolvedSpectralHoleDensity(ResolvedSpectralCarrierDensity):
621    r"""Resolved spectral hole density.
622
623    Note:
624        `energies`: Electron energies [$\mathrm{eV}$].
625        `rsv_values`: Resolved spectral hole density values
626            [$\mathrm{eV^{-1}}$].
627    """

Resolved spectral hole density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Resolved spectral hole density values [$\mathrm{eV^{-1}}$].

class BandResolvedSpectralCarrierDensity(ResolvedSpectralCarrierDensity):
630class BandResolvedSpectralCarrierDensity(ResolvedSpectralCarrierDensity):
631    r"""Band resolved spectral carrier density.
632
633    Note:
634        `energies`: Electron energies [$\mathrm{eV}$].
635        `rsv_values`: Band resolved spectral carrier density values
636            [$\mathrm{eV^{-1}}$].
637
638    Note:
639        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
640    """
641
642    def ret_rsv_fill_type(self, *, tolerance: Real = 0.0) -> dict[int, str]:
643        r"""Return band resolved fill type.
644
645        Args:
646            tolerance: Minimum distance between Fermi level and band edges
647                for band fill type to be determined [$\mathrm{eV}$].
648
649        Returns:
650            Band resolved fill type.
651        """
652        rsv_fill_type = {}
653        for i, edos_values in self.rsv_edos.rsv_values.items():
654            band_energies = self.energies[edos_values > 0.0]
655            if (
656                np.amin(band_energies) < self.fermi_lv - tolerance
657                and np.amax(band_energies) > self.fermi_lv + tolerance
658            ):
659                rsv_fill_type[i] = "metallic"
660            elif np.all(band_energies < self.fermi_lv + tolerance):
661                rsv_fill_type[i] = "filled"
662            elif np.all(band_energies > self.fermi_lv - tolerance):
663                rsv_fill_type[i] = "empty"
664            else:
665                rsv_fill_type[i] = "undetermined"
666        return rsv_fill_type
667
668    def ret_cell_rsv(
669        self, cell_type, *, tolerance: Real = 0.0
670    ) -> list[CellResolvedSpectralCarrierDensity, ...]:
671        r"""Return cell resolved spectral carrier densities.
672
673        Args:
674            cell_type: Cell type ('sq' ord 'ib').
675            tolerance: Minimum distance between Fermi level and band edges
676                for band fill type to be determined [$\mathrm{eV}$].
677
678        Returns:
679            List of cell resolved spectral carrier densities.
680
681        Raises:
682            ValueError: If cell type is not 'sq' or 'ib'.
683        """
684        if cell_type not in {"sq", "ib"}:
685            raise ValueError("Cell type must be 'sq' or 'ib'!")
686
687        cell_rsv_seq = []
688        rsv_fill_type = self.ret_rsv_fill_type(tolerance=tolerance)
689
690        if cell_type == "sq":
691
692            if set(rsv_fill_type.values()) == {"filled", "empty"}:
693                cell_rsv_edos_values = {"v": 0, "c": 0}
694                rsv_edos_values = self.rsv_edos.rsv_values
695                for band_i, fill_type in rsv_fill_type.items():
696                    edos_values = rsv_edos_values[band_i]
697                    if fill_type == "filled":
698                        cell_rsv_edos_values["v"] += edos_values
699                    if fill_type == "empty":
700                        cell_rsv_edos_values["c"] += edos_values
701                cell_rsv_edos = CellResolvedElectronDensityOfStates(
702                    self.energies, cell_rsv_edos_values
703                )
704                cell_rsv = type(self).total.cell_rsv(
705                    cell_rsv_edos,
706                    fermi_lv=self.fermi_lv,
707                    temperature=self.temperature,
708                )
709                cell_rsv_seq.append(cell_rsv)
710
711        elif cell_type == "ib":
712
713            if set(rsv_fill_type.values()) == {"filled", "metallic", "empty"}:
714                cell_rsv_edos_values = {"v": 0, "i": 0, "c": 0}
715                rsv_edos_values = self.rsv_edos.rsv_values
716                for band_i, fill_type in rsv_fill_type.items():
717                    edos_values = rsv_edos_values[band_i]
718                    if fill_type == "filled":
719                        cell_rsv_edos_values["v"] += edos_values
720                    if fill_type == "metallic":
721                        cell_rsv_edos_values["i"] += edos_values
722                    if fill_type == "empty":
723                        cell_rsv_edos_values["c"] += edos_values
724                cell_rsv_edos = CellResolvedElectronDensityOfStates(
725                    self.energies, cell_rsv_edos_values
726                )
727                cell_rsv = type(self).total.cell_rsv(
728                    cell_rsv_edos,
729                    fermi_lv=self.fermi_lv,
730                    temperature=self.temperature,
731                )
732                cell_rsv_seq.append(cell_rsv)
733
734            if set(rsv_fill_type.values()) == {"filled", "empty"}:
735                rsv_edos_values = self.rsv_edos.rsv_values
736
737                rsv_edos_values_filled = [
738                    rsv_edos_values[band_i]
739                    for band_i, fill_type in rsv_fill_type.items()
740                    if fill_type == "filled"
741                ]
742                rsv_edos_values_filled.sort(key=lambda x: x.min())
743
744                rsv_edos_values_empty = [
745                    rsv_edos_values[band_i]
746                    for band_i, fill_type in rsv_fill_type.items()
747                    if fill_type == "empty"
748                ]
749                rsv_edos_values_empty.sort(key=lambda x: x.min())
750
751                if len(rsv_edos_values_empty) > 1:
752                    cell_rsv_edos_values = {
753                        "v": sum(rsv_edos_values_filled),
754                        "i": rsv_edos_values_empty[0],
755                        "c": sum(rsv_edos_values_empty[1:]),
756                    }
757                    cell_rsv_edos = CellResolvedElectronDensityOfStates(
758                        self.energies, cell_rsv_edos_values
759                    )
760                    cell_rsv = type(self).total.cell_rsv(
761                        cell_rsv_edos,
762                        fermi_lv=self.fermi_lv,
763                        temperature=self.temperature,
764                    )
765                    cell_rsv_seq.append(cell_rsv)
766
767                if len(rsv_edos_values_filled) > 1:
768                    cell_rsv_edos_values = {
769                        "v": sum(rsv_edos_values_filled[:-1]),
770                        "i": rsv_edos_values_filled[-1],
771                        "c": sum(rsv_edos_values_empty),
772                    }
773                    cell_rsv_edos = CellResolvedElectronDensityOfStates(
774                        self.energies, cell_rsv_edos_values
775                    )
776                    cell_rsv = type(self).total.cell_rsv(
777                        cell_rsv_edos,
778                        fermi_lv=self.fermi_lv,
779                        temperature=self.temperature,
780                    )
781                    cell_rsv_seq.append(cell_rsv)
782
783        return cell_rsv_seq

Band resolved spectral carrier density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Band resolved spectral carrier density values [$\mathrm{eV^{-1}}$].

Note:

See madman.analysis.spectrum.BandResolvedEnergySpectrum for details.

def ret_rsv_fill_type(self, *, tolerance: numbers.Real = 0.0) -> dict[int, str]:
642    def ret_rsv_fill_type(self, *, tolerance: Real = 0.0) -> dict[int, str]:
643        r"""Return band resolved fill type.
644
645        Args:
646            tolerance: Minimum distance between Fermi level and band edges
647                for band fill type to be determined [$\mathrm{eV}$].
648
649        Returns:
650            Band resolved fill type.
651        """
652        rsv_fill_type = {}
653        for i, edos_values in self.rsv_edos.rsv_values.items():
654            band_energies = self.energies[edos_values > 0.0]
655            if (
656                np.amin(band_energies) < self.fermi_lv - tolerance
657                and np.amax(band_energies) > self.fermi_lv + tolerance
658            ):
659                rsv_fill_type[i] = "metallic"
660            elif np.all(band_energies < self.fermi_lv + tolerance):
661                rsv_fill_type[i] = "filled"
662            elif np.all(band_energies > self.fermi_lv - tolerance):
663                rsv_fill_type[i] = "empty"
664            else:
665                rsv_fill_type[i] = "undetermined"
666        return rsv_fill_type

Return band resolved fill type.

Arguments:
  • tolerance: Minimum distance between Fermi level and band edges for band fill type to be determined [$\mathrm{eV}$].
Returns:

Band resolved fill type.

def ret_cell_rsv( self, cell_type, *, tolerance: numbers.Real = 0.0) -> list[CellResolvedSpectralCarrierDensity, ...]:
668    def ret_cell_rsv(
669        self, cell_type, *, tolerance: Real = 0.0
670    ) -> list[CellResolvedSpectralCarrierDensity, ...]:
671        r"""Return cell resolved spectral carrier densities.
672
673        Args:
674            cell_type: Cell type ('sq' ord 'ib').
675            tolerance: Minimum distance between Fermi level and band edges
676                for band fill type to be determined [$\mathrm{eV}$].
677
678        Returns:
679            List of cell resolved spectral carrier densities.
680
681        Raises:
682            ValueError: If cell type is not 'sq' or 'ib'.
683        """
684        if cell_type not in {"sq", "ib"}:
685            raise ValueError("Cell type must be 'sq' or 'ib'!")
686
687        cell_rsv_seq = []
688        rsv_fill_type = self.ret_rsv_fill_type(tolerance=tolerance)
689
690        if cell_type == "sq":
691
692            if set(rsv_fill_type.values()) == {"filled", "empty"}:
693                cell_rsv_edos_values = {"v": 0, "c": 0}
694                rsv_edos_values = self.rsv_edos.rsv_values
695                for band_i, fill_type in rsv_fill_type.items():
696                    edos_values = rsv_edos_values[band_i]
697                    if fill_type == "filled":
698                        cell_rsv_edos_values["v"] += edos_values
699                    if fill_type == "empty":
700                        cell_rsv_edos_values["c"] += edos_values
701                cell_rsv_edos = CellResolvedElectronDensityOfStates(
702                    self.energies, cell_rsv_edos_values
703                )
704                cell_rsv = type(self).total.cell_rsv(
705                    cell_rsv_edos,
706                    fermi_lv=self.fermi_lv,
707                    temperature=self.temperature,
708                )
709                cell_rsv_seq.append(cell_rsv)
710
711        elif cell_type == "ib":
712
713            if set(rsv_fill_type.values()) == {"filled", "metallic", "empty"}:
714                cell_rsv_edos_values = {"v": 0, "i": 0, "c": 0}
715                rsv_edos_values = self.rsv_edos.rsv_values
716                for band_i, fill_type in rsv_fill_type.items():
717                    edos_values = rsv_edos_values[band_i]
718                    if fill_type == "filled":
719                        cell_rsv_edos_values["v"] += edos_values
720                    if fill_type == "metallic":
721                        cell_rsv_edos_values["i"] += edos_values
722                    if fill_type == "empty":
723                        cell_rsv_edos_values["c"] += edos_values
724                cell_rsv_edos = CellResolvedElectronDensityOfStates(
725                    self.energies, cell_rsv_edos_values
726                )
727                cell_rsv = type(self).total.cell_rsv(
728                    cell_rsv_edos,
729                    fermi_lv=self.fermi_lv,
730                    temperature=self.temperature,
731                )
732                cell_rsv_seq.append(cell_rsv)
733
734            if set(rsv_fill_type.values()) == {"filled", "empty"}:
735                rsv_edos_values = self.rsv_edos.rsv_values
736
737                rsv_edos_values_filled = [
738                    rsv_edos_values[band_i]
739                    for band_i, fill_type in rsv_fill_type.items()
740                    if fill_type == "filled"
741                ]
742                rsv_edos_values_filled.sort(key=lambda x: x.min())
743
744                rsv_edos_values_empty = [
745                    rsv_edos_values[band_i]
746                    for band_i, fill_type in rsv_fill_type.items()
747                    if fill_type == "empty"
748                ]
749                rsv_edos_values_empty.sort(key=lambda x: x.min())
750
751                if len(rsv_edos_values_empty) > 1:
752                    cell_rsv_edos_values = {
753                        "v": sum(rsv_edos_values_filled),
754                        "i": rsv_edos_values_empty[0],
755                        "c": sum(rsv_edos_values_empty[1:]),
756                    }
757                    cell_rsv_edos = CellResolvedElectronDensityOfStates(
758                        self.energies, cell_rsv_edos_values
759                    )
760                    cell_rsv = type(self).total.cell_rsv(
761                        cell_rsv_edos,
762                        fermi_lv=self.fermi_lv,
763                        temperature=self.temperature,
764                    )
765                    cell_rsv_seq.append(cell_rsv)
766
767                if len(rsv_edos_values_filled) > 1:
768                    cell_rsv_edos_values = {
769                        "v": sum(rsv_edos_values_filled[:-1]),
770                        "i": rsv_edos_values_filled[-1],
771                        "c": sum(rsv_edos_values_empty),
772                    }
773                    cell_rsv_edos = CellResolvedElectronDensityOfStates(
774                        self.energies, cell_rsv_edos_values
775                    )
776                    cell_rsv = type(self).total.cell_rsv(
777                        cell_rsv_edos,
778                        fermi_lv=self.fermi_lv,
779                        temperature=self.temperature,
780                    )
781                    cell_rsv_seq.append(cell_rsv)
782
783        return cell_rsv_seq

Return cell resolved spectral carrier densities.

Arguments:
  • cell_type: Cell type ('sq' ord 'ib').
  • tolerance: Minimum distance between Fermi level and band edges for band fill type to be determined [$\mathrm{eV}$].
Returns:

List of cell resolved spectral carrier densities.

Raises:
  • ValueError: If cell type is not 'sq' or 'ib'.
class BandResolvedSpectralElectronDensity(ResolvedSpectralElectronDensity, BandResolvedSpectralCarrierDensity):
786class BandResolvedSpectralElectronDensity(
787    ResolvedSpectralElectronDensity, BandResolvedSpectralCarrierDensity
788):
789    r"""Band resolved spectral electron density.
790
791    Note:
792        `energies`: Electron energies [$\mathrm{eV}$].
793        `rsv_values`: Band resolved spectral electron density values
794            [$\mathrm{eV^{-1}}$].
795
796    Note:
797        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
798    """

Band resolved spectral electron density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Band resolved spectral electron density values [$\mathrm{eV^{-1}}$].

Note:

See madman.analysis.spectrum.BandResolvedEnergySpectrum for details.

class BandResolvedSpectralHoleDensity(ResolvedSpectralHoleDensity, BandResolvedSpectralCarrierDensity):
801class BandResolvedSpectralHoleDensity(
802    ResolvedSpectralHoleDensity, BandResolvedSpectralCarrierDensity
803):
804    r"""Band resolved spectral hole density.
805
806    Note:
807        `energies`: Electron energies [$\mathrm{eV}$].
808        `rsv_values`: Band resolved spectral hole density values
809            [$\mathrm{eV^{-1}}$].
810
811    Note:
812        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
813    """

Band resolved spectral hole density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Band resolved spectral hole density values [$\mathrm{eV^{-1}}$].

Note:

See madman.analysis.spectrum.BandResolvedEnergySpectrum for details.

class CellResolvedSpectralCarrierDensity(ResolvedSpectralCarrierDensity):
816class CellResolvedSpectralCarrierDensity(ResolvedSpectralCarrierDensity):
817    r"""Cell resolved spectral carrier density.
818
819    Note:
820        `energies`: Electron energies [$\mathrm{eV}$].
821        `rsv_values`: Cell resolved spectral carrier density values
822            [$\mathrm{eV^{-1}}$].
823
824    Note:
825        See `madman.analysis.spectrum.CellResolvedEnergySpectrum` for details.
826    """
827    def ret_rsv_fill_type(self, *, tolerance: Real = 0.0) -> dict[int, str]:
828        r"""Return cell resolved fill type.
829
830        Args:
831            tolerance: Minimum distance between Fermi level and band edges
832                for band fill type to be determined [$\mathrm{eV}$].
833
834        Returns:
835            Cell resolved fill type.
836        """
837        rsv_fill_type = {}
838        for i, edos_values in self.rsv_edos.rsv_values.items():
839            band_energies = self.energies[edos_values > 0.0]
840            if (
841                np.amin(band_energies) < self.fermi_lv - tolerance
842                and np.amax(band_energies) > self.fermi_lv + tolerance
843            ):
844                rsv_fill_type[i] = "metallic"
845            elif np.all(band_energies < self.fermi_lv + tolerance):
846                rsv_fill_type[i] = "filled"
847            elif np.all(band_energies > self.fermi_lv - tolerance):
848                rsv_fill_type[i] = "empty"
849            else:
850                rsv_fill_type[i] = "undetermined"
851        return rsv_fill_type

Cell resolved spectral carrier density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Cell resolved spectral carrier density values [$\mathrm{eV^{-1}}$].

Note:

See madman.analysis.spectrum.CellResolvedEnergySpectrum for details.

def ret_rsv_fill_type(self, *, tolerance: numbers.Real = 0.0) -> dict[int, str]:
827    def ret_rsv_fill_type(self, *, tolerance: Real = 0.0) -> dict[int, str]:
828        r"""Return cell resolved fill type.
829
830        Args:
831            tolerance: Minimum distance between Fermi level and band edges
832                for band fill type to be determined [$\mathrm{eV}$].
833
834        Returns:
835            Cell resolved fill type.
836        """
837        rsv_fill_type = {}
838        for i, edos_values in self.rsv_edos.rsv_values.items():
839            band_energies = self.energies[edos_values > 0.0]
840            if (
841                np.amin(band_energies) < self.fermi_lv - tolerance
842                and np.amax(band_energies) > self.fermi_lv + tolerance
843            ):
844                rsv_fill_type[i] = "metallic"
845            elif np.all(band_energies < self.fermi_lv + tolerance):
846                rsv_fill_type[i] = "filled"
847            elif np.all(band_energies > self.fermi_lv - tolerance):
848                rsv_fill_type[i] = "empty"
849            else:
850                rsv_fill_type[i] = "undetermined"
851        return rsv_fill_type

Return cell resolved fill type.

Arguments:
  • tolerance: Minimum distance between Fermi level and band edges for band fill type to be determined [$\mathrm{eV}$].
Returns:

Cell resolved fill type.

class CellResolvedSpectralElectronDensity(ResolvedSpectralElectronDensity, CellResolvedSpectralCarrierDensity):
854class CellResolvedSpectralElectronDensity(
855    ResolvedSpectralElectronDensity, CellResolvedSpectralCarrierDensity
856):
857    r"""Cell resolved spectral electron density.
858
859    Note:
860        `energies`: Electron energies [$\mathrm{eV}$].
861        `rsv_values`: Cell resolved spectral electron density values
862            [$\mathrm{eV^{-1}}$].
863
864    Note:
865        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
866    """

Cell resolved spectral electron density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Cell resolved spectral electron density values [$\mathrm{eV^{-1}}$].

Note:

See madman.analysis.spectrum.BandResolvedEnergySpectrum for details.

class CellResolvedSpectralHoleDensity(ResolvedSpectralHoleDensity, CellResolvedSpectralCarrierDensity):
869class CellResolvedSpectralHoleDensity(
870    ResolvedSpectralHoleDensity, CellResolvedSpectralCarrierDensity
871):
872    r"""Cell resolved spectral hole density.
873
874    Note:
875        `energies`: Electron energies [$\mathrm{eV}$].
876        `rsv_values`: Cell resolved spectral hole density values
877            [$\mathrm{eV^{-1}}$].
878
879    Note:
880        See `madman.analysis.spectrum.BandResolvedEnergySpectrum` for details.
881    """

Cell resolved spectral hole density.

Note:

energies: Electron energies [$\mathrm{eV}$]. rsv_values: Cell resolved spectral hole density values [$\mathrm{eV^{-1}}$].

Note:

See madman.analysis.spectrum.BandResolvedEnergySpectrum for details.