scambio.special

Special functions.

  1r"""Special functions."""
  2
  3import numpy as np
  4from collections.abc import Sequence
  5from functools import lru_cache
  6from mpmath import fp
  7from numbers import Real, Integral
  8from scambio.constant import Constant
  9
 10
 11def rectangle(
 12    x: Sequence[Sequence[Real, ...], ...],
 13    *,
 14    a: Sequence[Real, ...],
 15    b: Sequence[Real, ...],
 16) -> np.ndarray[float]:
 17    r"""Rectangular function.
 18
 19    Args:
 20        x: Independent variable.
 21        a: Rectangle onset.
 22        b: Rectangle offset.
 23
 24    Returns:
 25        Dependent variable.
 26    """
 27    x = np.asarray(x, dtype=float).reshape(1, -1)
 28    a = np.asarray(a, dtype=float).reshape(-1, 1)
 29    b = np.asarray(b, dtype=float).reshape(-1, 1)
 30    y = np.logical_and(a <= x, x <= b).astype(float).squeeze()
 31    return y
 32
 33
 34def bose_einstein_prim(
 35    order: Integral, energy: Real, *, temperature: Real, potential: Real
 36) -> complex | float:
 37    r"""Bose-Einstein primitive.
 38
 39    Note:
 40        See [`ibei` documentation](https://ibei.readthedocs.io/en/stable/)
 41        for details.
 42
 43    Args:
 44        order: Order (n).
 45        energy: Photon energy [$\mathrm{eV}$].
 46        temperature: Temperature [$\mathrm{K}$].
 47        potential: Chemical potential [$\mathrm{eV}$].
 48
 49    Returns:
 50        Bose-Einstein primitive value
 51        [$\mathrm{eV^{n - 2} \, s^{-1} \, cm^{-2}}$].
 52    """
 53    if not isinstance(order, Integral) or not order >= 2:
 54        print("BE order must be an integer greater than or equal to 2!")
 55        return fp.nan
 56
 57    if not isinstance(energy, Real) or not energy >= 0.0:
 58        print("Photon energy must be a nonnegative real number!")
 59        return fp.nan
 60
 61    if not isinstance(temperature, Real) or not temperature > 0.0:
 62        print("Temperature must be a positive real number!")
 63        return fp.nan
 64
 65    if not isinstance(potential, Real):
 66        print("Chemical potential must be a real number!")
 67        return fp.nan
 68
 69    if np.isnan(potential):
 70        return fp.nan
 71
 72    if energy == fp.inf:
 73        return 0.0
 74
 75    factor = -2.0 * fp.pi / Constant.c**2 / Constant.h**3 * fp.factorial(order)
 76    if energy == potential == 0.0:
 77        return (
 78            factor
 79            * (Constant.k * temperature) ** (order + 1)
 80            * fp.polylog(order + 1, 1.0)
 81        )
 82
 83    if energy == potential:
 84        return np.nan
 85
 86    energy_red = (energy - potential) / (Constant.k * temperature)
 87    return factor * sum(
 88        [
 89            fp.factorial(order - i) ** -1
 90            * (Constant.k * temperature) ** (i + 1)
 91            * energy ** (order - i)
 92            * fp.polylog(i + 1, fp.exp(-energy_red))
 93            for i in range(order + 1)
 94        ]
 95    )
 96
 97
 98@lru_cache(maxsize=1000)
 99def bose_einstein_integr(
100    order: Integral, energy: Real, *, temperature: Real, potential: Real
101) -> float:
102    r"""Bose-Einstein integral.
103
104    Note:
105        See [`ibei` documentation](https://ibei.readthedocs.io/en/stable/)
106        for details.
107
108        If the chemical potential is greater than the photon energy, the
109        integrand contains a singularity that makes the integral underfined.
110        However, the Cauchy principal value is finite and equals the real
111        part of the Bose-Einstein primitive, because the imaginary part
112        cancels out.
113
114    Args:
115        order: Order (n).
116        energy: Photon energy [$\mathrm{eV}$].
117        temperature: Temperature [$\mathrm{K}$].
118        potential: Chemical potential [$\mathrm{eV}$].
119
120    Returns:
121        Bose-Einstein integral value
122        [$\mathrm{eV^{n - 2} \, s^{-1} \, cm^{-2}}$].
123    """
124    return -bose_einstein_prim(
125        order, energy, temperature=temperature, potential=potential
126    ).real
def rectangle( x: collections.abc.Sequence[collections.abc.Sequence[numbers.Real, ...], ...], *, a: collections.abc.Sequence[numbers.Real, ...], b: collections.abc.Sequence[numbers.Real, ...]) -> numpy.ndarray[float]:
12def rectangle(
13    x: Sequence[Sequence[Real, ...], ...],
14    *,
15    a: Sequence[Real, ...],
16    b: Sequence[Real, ...],
17) -> np.ndarray[float]:
18    r"""Rectangular function.
19
20    Args:
21        x: Independent variable.
22        a: Rectangle onset.
23        b: Rectangle offset.
24
25    Returns:
26        Dependent variable.
27    """
28    x = np.asarray(x, dtype=float).reshape(1, -1)
29    a = np.asarray(a, dtype=float).reshape(-1, 1)
30    b = np.asarray(b, dtype=float).reshape(-1, 1)
31    y = np.logical_and(a <= x, x <= b).astype(float).squeeze()
32    return y

Rectangular function.

Arguments:
  • x: Independent variable.
  • a: Rectangle onset.
  • b: Rectangle offset.
Returns:

Dependent variable.

def bose_einstein_prim( order: numbers.Integral, energy: numbers.Real, *, temperature: numbers.Real, potential: numbers.Real) -> complex | float:
35def bose_einstein_prim(
36    order: Integral, energy: Real, *, temperature: Real, potential: Real
37) -> complex | float:
38    r"""Bose-Einstein primitive.
39
40    Note:
41        See [`ibei` documentation](https://ibei.readthedocs.io/en/stable/)
42        for details.
43
44    Args:
45        order: Order (n).
46        energy: Photon energy [$\mathrm{eV}$].
47        temperature: Temperature [$\mathrm{K}$].
48        potential: Chemical potential [$\mathrm{eV}$].
49
50    Returns:
51        Bose-Einstein primitive value
52        [$\mathrm{eV^{n - 2} \, s^{-1} \, cm^{-2}}$].
53    """
54    if not isinstance(order, Integral) or not order >= 2:
55        print("BE order must be an integer greater than or equal to 2!")
56        return fp.nan
57
58    if not isinstance(energy, Real) or not energy >= 0.0:
59        print("Photon energy must be a nonnegative real number!")
60        return fp.nan
61
62    if not isinstance(temperature, Real) or not temperature > 0.0:
63        print("Temperature must be a positive real number!")
64        return fp.nan
65
66    if not isinstance(potential, Real):
67        print("Chemical potential must be a real number!")
68        return fp.nan
69
70    if np.isnan(potential):
71        return fp.nan
72
73    if energy == fp.inf:
74        return 0.0
75
76    factor = -2.0 * fp.pi / Constant.c**2 / Constant.h**3 * fp.factorial(order)
77    if energy == potential == 0.0:
78        return (
79            factor
80            * (Constant.k * temperature) ** (order + 1)
81            * fp.polylog(order + 1, 1.0)
82        )
83
84    if energy == potential:
85        return np.nan
86
87    energy_red = (energy - potential) / (Constant.k * temperature)
88    return factor * sum(
89        [
90            fp.factorial(order - i) ** -1
91            * (Constant.k * temperature) ** (i + 1)
92            * energy ** (order - i)
93            * fp.polylog(i + 1, fp.exp(-energy_red))
94            for i in range(order + 1)
95        ]
96    )

Bose-Einstein primitive.

Note:

See ibei documentation for details.

Arguments:
  • order: Order (n).
  • energy: Photon energy [$\mathrm{eV}$].
  • temperature: Temperature [$\mathrm{K}$].
  • potential: Chemical potential [$\mathrm{eV}$].
Returns:

Bose-Einstein primitive value [$\mathrm{eV^{n - 2} \, s^{-1} \, cm^{-2}}$].

@lru_cache(maxsize=1000)
def bose_einstein_integr( order: numbers.Integral, energy: numbers.Real, *, temperature: numbers.Real, potential: numbers.Real) -> float:
 99@lru_cache(maxsize=1000)
100def bose_einstein_integr(
101    order: Integral, energy: Real, *, temperature: Real, potential: Real
102) -> float:
103    r"""Bose-Einstein integral.
104
105    Note:
106        See [`ibei` documentation](https://ibei.readthedocs.io/en/stable/)
107        for details.
108
109        If the chemical potential is greater than the photon energy, the
110        integrand contains a singularity that makes the integral underfined.
111        However, the Cauchy principal value is finite and equals the real
112        part of the Bose-Einstein primitive, because the imaginary part
113        cancels out.
114
115    Args:
116        order: Order (n).
117        energy: Photon energy [$\mathrm{eV}$].
118        temperature: Temperature [$\mathrm{K}$].
119        potential: Chemical potential [$\mathrm{eV}$].
120
121    Returns:
122        Bose-Einstein integral value
123        [$\mathrm{eV^{n - 2} \, s^{-1} \, cm^{-2}}$].
124    """
125    return -bose_einstein_prim(
126        order, energy, temperature=temperature, potential=potential
127    ).real

Bose-Einstein integral.

Note:

See ibei documentation for details.

If the chemical potential is greater than the photon energy, the integrand contains a singularity that makes the integral underfined. However, the Cauchy principal value is finite and equals the real part of the Bose-Einstein primitive, because the imaginary part cancels out.

Arguments:
  • order: Order (n).
  • energy: Photon energy [$\mathrm{eV}$].
  • temperature: Temperature [$\mathrm{K}$].
  • potential: Chemical potential [$\mathrm{eV}$].
Returns:

Bose-Einstein integral value [$\mathrm{eV^{n - 2} \, s^{-1} \, cm^{-2}}$].