"""
Module of dimensionless parameters related to collisions.
"""
__all__ = [
"coupling_parameter",
"Knudsen_number",
]
from typing import Literal
import astropy.units as u
import numpy as np
from astropy.constants.si import e, eps0, k_B
from plasmapy import particles
from plasmapy.formulary.collisions import lengths, misc
from plasmapy.formulary.mathematics import Fermi_integral
from plasmapy.formulary.quantum import (
Wigner_Seitz_radius,
chemical_potential,
thermal_deBroglie_wavelength,
)
from plasmapy.utils.decorators import validate_quantities
[docs]
@validate_quantities(
T={"can_be_negative": False, "equivalencies": u.temperature_energy()},
n_e={"can_be_negative": False},
)
def coupling_parameter(
T: u.Quantity[u.K],
n_e: u.Quantity[u.m**-3],
species,
z_mean: float = np.nan,
V: u.Quantity[u.m / u.s] = np.nan * u.m / u.s,
method: Literal["classical", "quantum"] = "classical",
) -> u.Quantity[u.dimensionless_unscaled]:
r"""
Ratio of the Coulomb energy to the kinetic (usually thermal) energy.
Classical plasmas are weakly coupled (:math:`Γ ≪ 1`, where :math:`Γ`
is the coupling parameter). Dense plasmas tend to have significant
to strong coupling (:math:`Γ ≥ 1`\ ). For more details, see the
notes section below.
Parameters
----------
T : `~astropy.units.Quantity`
Temperature in units of temperature or energy per particle,
which is assumed to be equal for both the test particle and the
target particle.
n_e : `~astropy.units.Quantity`
The electron number density in units convertible to per cubic
meter.
species : `tuple`
A tuple containing string representations of the test particle
(listed first) and the target particle (listed second).
z_mean : `~astropy.units.Quantity`, optional
The average ionization (arithmetic mean) of a plasma for which a
macroscopic description is valid. This parameter is used to
compute the average ion density (given the average ionization
and electron density) for calculating the ion sphere radius for
non-classical impact parameters. ``z_mean`` is a required
parameter if ``method`` is ``"ls_full_interp"``,
``"hls_max_interp"``, or ``"hls_full_interp"``.
V : `~astropy.units.Quantity`, optional
The relative velocity between particles. If not provided,
thermal velocity is assumed: :math:`μ V^2 \sim 2 k_B T` where
:math:`μ` is the reduced mass.
method : {``"classical"``, ``"quantum"``}, default: "classical"
The method by which to compute the coupling parameter: either
``"classical"`` or ``"quantum"``. The Notes section of this
docstring has more information about these two methods.
Returns
-------
coupling : `float` or `~numpy.ndarray`
The coupling parameter for a plasma.
Raises
------
`ValueError`
If the mass or charge of either particle cannot be found, or any
of the inputs contain incorrect values.
`~astropy.units.UnitConversionError`
If the units on any of the inputs are incorrect.
`TypeError`
If any of ``n_e``, ``T``, or ``V`` is not a
`~astropy.units.Quantity`.
`~plasmapy.utils.exceptions.RelativityError`
If the input velocity is same or greater than the speed of
light.
Warns
-----
: `~astropy.units.UnitsWarning`
If units are not provided, SI units are assumed.
: `~plasmapy.utils.exceptions.RelativityWarning`
If the input velocity is greater than 5% of the speed of light.
Notes
-----
The coupling parameter is given by
.. math::
Γ = \frac{E_{Coulomb}}{E_{Kinetic}}
The Coulomb energy is given by
.. math::
E_{Coulomb} = \frac{Z_1 Z_2 q_e^2}{4 π ε_0 r}
where :math:`r` is the Wigner-Seitz radius, and 1 and 2 refer to
particle species 1 and 2 between which we want to determine the
coupling.
In the classical case the kinetic energy is the thermal energy:
.. math::
E_{kinetic} = k_B T_e
The quantum case is more complex. The kinetic energy is dominated by
the Fermi energy, modulated by a correction factor based on the
ideal chemical potential. This is obtained more precisely by taking
the thermal kinetic energy and dividing by the degeneracy
parameter, modulated by the Fermi integral :cite:p:`gericke:2002`\ :
.. math::
E_{kinetic} = 2 k_B T_e / χ f_{3/2} (μ_{ideal} / k_B T_e)
where :math:`χ` is the degeneracy parameter, :math:`f_{3/2}` is the
Fermi integral, and :math:`μ_{ideal}` is the ideal chemical
potential.
The degeneracy parameter is given by
.. math::
χ = n_e Λ_{de Broglie} ^ 3
where :math:`n_e` is the electron density and :math:`Λ_{de Broglie}`
is the thermal de Broglie wavelength.
See equations 1.2, 1.3 and footnote 5 in :cite:t:`bonitz:1998` for
details on the ideal chemical potential.
Examples
--------
>>> import astropy.units as u
>>> n = 1e19 * u.m**-3
>>> T = 1e6 * u.K
>>> species = ("e", "p")
>>> coupling_parameter(T, n, species)
<Quantity 5.8033...e-05>
>>> coupling_parameter(T, n, species, V=1e6 * u.m / u.s)
<Quantity 5.8033...e-05>
"""
T, masses, charges, reduced_mass, V = misc._process_inputs( # noqa: SLF001
T=T, species=species, V=V
)
if np.isnan(z_mean):
# using mean charge to get average ion density.
# If you are running this, you should strongly consider giving
# a value of z_mean as an argument instead.
Z1 = np.abs(particles.atomic.charge_number(species[0]))
Z2 = np.abs(particles.atomic.charge_number(species[1]))
Z = (Z1 + Z2) / 2
# getting ion density from electron density
n_i = n_e / Z
else:
# getting ion density from electron density
n_i = n_e / z_mean
# getting Wigner-Seitz radius based on ion density
radius = Wigner_Seitz_radius(n_i)
# Coulomb potential energy between particles
if np.isnan(z_mean):
coulomb_energy = charges[0] * charges[1] / (4 * np.pi * eps0 * radius)
else:
coulomb_energy = (z_mean * e) ** 2 / (4 * np.pi * eps0 * radius)
if method == "classical":
# classical thermal kinetic energy
kinetic_energy = k_B * T
elif method == "quantum":
# quantum kinetic energy for dense plasmas
lambda_deBroglie = thermal_deBroglie_wavelength(T)
chem_potential = chemical_potential(n_e, T)
fermi_integral = Fermi_integral(chem_potential.si.value, 1.5)
denominator = (n_e * lambda_deBroglie**3) * fermi_integral
kinetic_energy = 2 * k_B * T / denominator
if np.all(np.imag(kinetic_energy) < 1e-15 * u.J):
kinetic_energy = np.real(kinetic_energy)
else:
raise ValueError(
"Kinetic energy should not be imaginary."
"Something went horribly wrong."
)
else:
raise ValueError(
f"Keyword 'method' must be either 'classical' or "
f"'quantum', instead of '{method}'."
)
return coulomb_energy / kinetic_energy
[docs]
@validate_quantities(
T={"can_be_negative": False, "equivalencies": u.temperature_energy()},
n_e={"can_be_negative": False},
)
def Knudsen_number(
characteristic_length,
T: u.Quantity[u.K],
n_e: u.Quantity[u.m**-3],
species,
z_mean: float = np.nan,
V: u.Quantity[u.m / u.s] = np.nan * u.m / u.s,
method: str = "classical",
) -> u.Quantity[u.dimensionless_unscaled]:
r"""
Knudsen number (dimensionless).
Parameters
----------
characteristic_length : `~astropy.units.Quantity`
Rough order-of-magnitude estimate of the relevant size of the
system.
T : `~astropy.units.Quantity`
Temperature in units of temperature or energy per particle,
which is assumed to be equal for both the test particle and the
target particle.
n_e : `~astropy.units.Quantity`
The electron number density in units convertible to m\ :sup:`-3`.
species : `tuple`
A tuple containing string representations of the test particle
(listed first) and the target particle (listed second).
z_mean : `~astropy.units.Quantity`, optional
The average ionization (arithmetic mean) of a plasma for which a
macroscopic description is valid. This parameter is used to
compute the average ion density (given the average ionization
and electron density) for calculating the ion sphere radius for
non-classical impact parameters. ``z_mean`` is a required
parameter if ``method`` is ``"ls_full_interp"``,
``"hls_max_interp"``, or ``"hls_full_interp"``.
V : `~astropy.units.Quantity`, optional
The relative velocity between particles. If not provided,
thermal velocity is assumed: :math:`μ V^2 \sim 2 k_B T` where
:math:`μ` is the reduced mass.
method : `str`, optional
The method by which to compute the Coulomb logarithm. The
default method is the classical straight-line Landau-Spitzer
method (``"classical"`` or ``"ls"``). The other 6 supported
methods are ``"ls_min_interp"``, ``"ls_full_interp"``,
``"ls_clamp_mininterp"``, ``"hls_min_interp"``,
``"hls_max_interp"``, and ``"hls_full_interp"``. Please refer
to the docstring of
`~plasmapy.formulary.collisions.coulomb.Coulomb_logarithm` for more
information about these methods.
Returns
-------
knudsen_param : `float` or `numpy.ndarray`
The dimensionless Knudsen number.
Raises
------
`ValueError`
If the mass or charge of either particle cannot be found, or any
of the inputs contain incorrect values.
`~astropy.units.UnitConversionError`
If the units on any of the inputs are incorrect.
`TypeError`
If any of ``n_e``, ``T``, or ``V`` is not a
`~astropy.units.Quantity`.
`~plasmapy.utils.exceptions.RelativityError`
If the input velocity is same or greater than the speed of
light.
Warns
-----
: `~astropy.units.UnitsWarning`
If units are not provided, SI units are assumed.
: `~plasmapy.utils.exceptions.RelativityWarning`
If the input velocity is greater than 5% of the speed of light.
Notes
-----
The `Knudsen number <https://en.wikipedia.org/wiki/Knudsen_number>`_
is given by
.. math::
Kn = \frac{λ_{mfp}}{L}
where :math:`λ_{mfp}` is the collisional mean free path for
particles in a plasma and :math:`L` is the characteristic scale
length of interest.
The characteristic scale length is typically the plasma size or the
size of a diagnostic (such as the length or radius of a Langmuir
probe tip). The Knudsen number tells us whether collisional effects
are important on this scale length.
Examples
--------
>>> import astropy.units as u
>>> L = 1e-3 * u.m
>>> n = 1e19 * u.m**-3
>>> T = 1e6 * u.K
>>> species = ("e", "p")
>>> Knudsen_number(L, T, n, species)
<Quantity 7839.5...>
>>> Knudsen_number(L, T, n, species, V=1e6 * u.m / u.s)
<Quantity 10.91773...>
"""
path_length = lengths.mean_free_path(
T=T, n_e=n_e, species=species, z_mean=z_mean, V=V, method=method
)
return path_length / characteristic_length