Пример #1
0
def mass_density(
    density: [u.m**-3, u.kg / (u.m**3)],
    particle: Optional[str] = None,
    z_mean: Optional[numbers.Real] = None,
) -> u.kg / u.m**3:
    """Utility function to merge two possible inputs for particle charge.

    Parameters
    ----------
    density : ~astropy.units.Quantity
        Either a particle density (number of particles per unit volume, in units
        of 1/m^3) or a mass density (in units of kg/m^3 or equivalent).

    particle : str, optional
        Representation of the particle species (e.g., `'p'` for protons, `'D+'`
        for deuterium, or `'He-4 +1'` for singly ionized helium-4),
        which defaults to electrons.  If no charge state information is
        provided, then the particles are assumed to be singly charged.

    z_mean : float
        An optional float describing the average ionization of a particle
        species.

    Raises
    ------
    ValueError
        If the `density` has units inconvertible to either a particle density
        or a mass density, or if you pass in a number density without a particle.

    Returns
    -------
    ~astropy.units.Quantity
        The mass density calculated from all the provided sources of information.

    Examples
    -------
    >>> from astropy import units as u
    >>> mass_density(1 * u.m ** -3,'p')
    <Quantity 1.67353...e-27 kg / m3>
    >>> mass_density(4 * u.m ** -3,'D+')
    <Quantity 1.33779...e-26 kg / m3>

    """
    # validate_quantities ensures we have units of u.kg/u.m**3 or 1/u.m**3
    rho = density
    if not rho.unit.is_equivalent(u.kg / u.m**3):
        if particle:
            m_i = particles.particle_mass(particle)
            Z = _grab_charge(particle, z_mean)
            rho = density * m_i + Z * density * m_e
        else:
            raise ValueError(
                f"If passing a number density, you must pass a "
                f"particle (not {particle}) to calculate the mass density!")

    return rho
Пример #2
0
 def __init__(self, T_e, n_e, Z=None, particle='p'):
     """
     Initialize plasma paramters.
     The most basic description is composition (ion), temperature,
     density, and ionization.
     """
     self.T_e = T_e
     self.n_e = n_e
     self.particle = particle
     self.Z = _grab_charge(particle, Z)
     # extract mass from particle
     self.ionMass = particle_mass(self.particle)
Пример #3
0
def args_to_lite_args(kwargs):
    """
    Converts a dict of args for the spectral density function and converts
    them to input for the lite function.

    Used to facilitate testing the two functions against each other.
    """
    keys = list(kwargs.keys())

    if "wavelengths" in keys:
        kwargs["wavelengths"] = kwargs["wavelengths"].to(u.m).value
    if "probe_wavelength" in keys:
        kwargs["probe_wavelength"] = kwargs["probe_wavelength"].to(u.m).value
    if "n" in keys:
        kwargs["n"] = kwargs["n"].to(u.m**-3).value
    if "T_e" in keys:
        kwargs["T_e"] = (kwargs["T_e"] / const.k_B).to(u.K).value
    if "T_i" in keys:
        kwargs["T_i"] = (kwargs["T_i"] / const.k_B).to(u.K).value
    if "electron_vel" in keys:
        kwargs["electron_vel"] = kwargs["electron_vel"].to(u.m / u.s).value
    if "ion_vel" in keys:
        kwargs["ion_vel"] = kwargs["ion_vel"].to(u.m / u.s).value

    if kwargs["T_e"].size == 1:
        kwargs["T_e"] = np.array([
            kwargs["T_e"],
        ])
    if kwargs["T_i"].size == 1:
        kwargs["T_i"] = np.array([
            kwargs["T_i"],
        ])

    if not isinstance(kwargs["ions"], list):
        kwargs["ions"] = [
            kwargs["ions"],
        ]

    ion_z = np.zeros(len(kwargs["ions"]))
    ion_mass = np.zeros(len(kwargs["ions"]))
    for i, particle in enumerate(kwargs["ions"]):
        if not isinstance(particle, Particle):
            particle = Particle(particle)
        ion_z[i] = particle.charge_number
        ion_mass[i] = particle_mass(particle).to(u.kg).value
    kwargs["ion_z"] = ion_z
    kwargs["ion_mass"] = ion_mass
    del kwargs["ions"]

    return kwargs
Пример #4
0
def deBroglie_wavelength(V: u.m / u.s, particle) -> u.m:
    r"""
    Calculates the de Broglie wavelength.

    Parameters
    ----------
    V : ~astropy.units.Quantity
        Particle velocity in units convertible to meters per second.

    particle : str or ~astropy.units.Quantity
        Representation of the particle species (e.g., `'e'`, `'p'`, `'D+'`,
        or `'He-4 1+'`, or the particle mass in units convertible to
        kilograms.

    Returns
    -------
    lambda_dB : ~astropy.units.Quantity
        The de Broglie wavelength in units of meters.

    Raises
    ------
    TypeError
        The velocity is not a `~astropy.units.Quantity` and cannot be
        converted into a ~astropy.units.Quantity.

    ~astropy.units.UnitConversionError
        If the velocity is not in appropriate units.

    ~plasmapy.utils.RelativityError
        If the magnitude of `V` is faster than the speed of light.

    Warns
    -----
    ~astropy.units.UnitsWarning
        If units are not provided, SI units are assumed

    Notes
    -----
    The de Broglie wavelength is given by

    .. math::

        \lambda_{dB} = \frac{h}{p} = \frac{h}{\gamma m V}

    where :math:`h` is the Planck constant, :math:`p` is the
    relativistic momentum of the particle, :math:`gamma` is the
    Lorentz factor, :math:`m` is the particle's mass, and :math:`V` is the
    particle's velocity.

    Examples
    --------
    >>> from astropy import units as u
    >>> velocity = 1.4e7 * u.m / u.s
    >>> deBroglie_wavelength(velocity, 'e')
    <Quantity 5.18997095e-11 m>
    >>> deBroglie_wavelength(V = 0 * u.m / u.s, particle = 'D+')
    <Quantity inf m>
    """

    V = np.abs(V)

    if np.any(V >= c):
        raise RelativityError("Velocity input in deBroglie_wavelength cannot "
                              "be greater than or equal to the speed of "
                              "light.")

    if not isinstance(particle, u.Quantity):
        try:
            # TODO: Replace with more general routine!
            m = particles.particle_mass(particle)
        except Exception:
            raise ValueError("Unable to find particle mass.")
    else:
        try:
            m = particle.to(u.kg)
        except Exception:
            raise u.UnitConversionError("The second argument for deBroglie"
                                        " wavelength must be either a "
                                        "representation of a particle or a"
                                        " Quantity with units of mass.")

    if V.size > 1:

        lambda_dBr = np.ones(V.shape) * np.inf * u.m
        indices = V.value != 0
        lambda_dBr[indices] = h / (m * V[indices] * Lorentz_factor(V[indices]))

    else:

        if V == 0 * u.m / u.s:
            lambda_dBr = np.inf * u.m
        else:
            lambda_dBr = h / (Lorentz_factor(V) * m * V)

    return lambda_dBr
Пример #5
0
def deBroglie_wavelength(V: u.m / u.s, particle) -> u.m:
    r"""
    Return the de Broglie wavelength.

    The de Broglie wavelength (:math:`λ_{dB}`) of a particle is defined by

    .. math::

        λ_{dB} = \frac{h}{p} = \frac{h}{γ m V}

    where :math:`h` is the Planck constant, :math:`p` is the
    relativistic momentum of the particle, :math:`γ` is the
    Lorentz factor, :math:`m` is the mass of the particle, and
    :math:`V` is the velocity of the particle.

    **Aliases:** `lambdaDB_`

    Parameters
    ----------
    V : `~astropy.units.Quantity`
        Particle velocity in units convertible to meters per second.

    particle : `str`, `~plasmapy.particles.particle_class.Particle`, or `~astropy.units.Quantity`
        An instance of `~plasmapy.particles.particle_class.Particle`, or
        an equivalent representation (e.g., ``'e'``, ``'p'``, ``'D+'``, or
        ``'He-4 1+'``), for the particle of interest, or the particle
        mass in units convertible to kg.  If a
        `~plasmapy.particles.particle_class.Particle` instance is given, then the
        particle mass is retrieved from the object.

    Returns
    -------
    lambda_dB : `~astropy.units.Quantity`
        The de Broglie wavelength in units of meters.

    Raises
    ------
    `TypeError`
        If the velocity is not a `~astropy.units.Quantity` and cannot be
        converted into a `~astropy.units.Quantity`.

    `~astropy.units.UnitConversionError`
        If the velocity is not in appropriate units.

    `~plasmapy.utils.exceptions.RelativityError`
        If the magnitude of ``V`` is larger than the speed of light.

    Warns
    -----
    : `~astropy.units.UnitsWarning`
        If units are not provided, SI units are assumed.

    Examples
    --------
    >>> from astropy import units as u
    >>> velocity = 1.4e7 * u.m / u.s
    >>> deBroglie_wavelength(velocity, 'e')
    <Quantity 5.18997095e-11 m>
    >>> deBroglie_wavelength(V = 0 * u.m / u.s, particle = 'D+')
    <Quantity inf m>
    """

    V = np.abs(V)

    if np.any(V >= c):
        raise RelativityError(
            "Velocity input in deBroglie_wavelength cannot "
            "be greater than or equal to the speed of "
            "light."
        )

    if not isinstance(particle, u.Quantity):
        try:
            # TODO: Replace with more general routine!
            m = particles.particle_mass(particle)
        except InvalidParticleError:
            raise ValueError("Unable to find particle mass.")
    else:
        try:
            m = particle.to(u.kg)
        except u.UnitConversionError as e:
            raise u.UnitConversionError(
                "The second argument for deBroglie_wavelength must be either a "
                "representation of a particle or a"
                " Quantity with units of mass."
            ) from e

    if V.size > 1:

        lambda_dBr = np.ones(V.shape) * np.inf * u.m
        indices = V.value != 0
        lambda_dBr[indices] = h / (m * V[indices] * Lorentz_factor(V[indices]))

    elif V == 0 * u.m / u.s:
        lambda_dBr = np.inf * u.m
    else:
        lambda_dBr = h / (Lorentz_factor(V) * m * V)

    return lambda_dBr
Пример #6
0
def gyrofrequency(B: u.T, particle="e-", signed=False, Z=None) -> u.rad / u.s:
    r"""Calculate the particle gyrofrequency in units of radians per second.

    Parameters
    ----------
    B : ~astropy.units.Quantity
        The magnetic field magnitude in units convertible to tesla.

    particle : str, optional
        Representation of the particle species (e.g., 'p' for protons, 'D+'
        for deuterium, or 'He-4 +1' for singly ionized helium-4),
        which defaults to electrons.  If no charge state information is
        provided, then the particles are assumed to be singly charged.

    signed : bool, optional
        The gyrofrequency can be defined as signed (negative for electron,
        positive for ion). Default is `False` (unsigned, i.e. always
        positive).

    Z : float or ~astropy.units.Quantity, optional
        The average ionization (arithmetic mean) for a plasma where the
        a macroscopic description is valid. If this quantity is not
        given then the atomic charge state (integer) of the ion
        is used. This is effectively an average gyrofrequency for the
        plasma where multiple charge states are present, and should
        not be interpreted as the gyrofrequency for any single particle.
        If not provided, it defaults to the integer charge of the `particle`.

    Returns
    -------
    omega_c : ~astropy.units.Quantity
        The particle gyrofrequency in units of radians per second

    Raises
    ------
    TypeError
        If the magnetic field is not a `Quantity` or particle is not of an
        appropriate type

    ValueError
        If the magnetic field contains invalid values or particle cannot be
        used to identify an particle or isotope

    Warns
    -----
    ~astropy.units.UnitsWarning
        If units are not provided, SI units are assumed

    Notes
    -----
    The particle gyrofrequency is the angular frequency of particle gyration
    around magnetic field lines and is given by:

    .. math::
        \omega_{ci} = \frac{Z e B}{m_i}

    The particle gyrofrequency is also known as the particle cyclotron
    frequency or the particle Larmor frequency.

    The recommended way to convert from angular frequency to frequency
    is to use an equivalency between cycles per second and Hertz, as
    Astropy's `dimensionles_angles` equivalency does not account for
    the factor of 2*pi needed during this conversion.  The
    `dimensionless_angles` equivalency is appropriate when dividing a
    velocity by an angular frequency to get a length scale.

    Examples
    --------
    >>> from astropy import units as u
    >>> gyrofrequency(0.1*u.T)
    <Quantity 1.7588...e+10 rad / s>
    >>> gyrofrequency(0.1*u.T, to_hz=True)
    <Quantity 2.79924...e+09 Hz>
    >>> gyrofrequency(0.1*u.T, signed=True)
    <Quantity -1.75882...e+10 rad / s>
    >>> gyrofrequency(0.01*u.T, 'p')
    <Quantity 957883.32... rad / s>
    >>> gyrofrequency(0.01*u.T, 'p', signed=True)
    <Quantity 957883.32... rad / s>
    >>> gyrofrequency(0.01*u.T, particle='T+')
    <Quantity 319964.5... rad / s>
    >>> gyrofrequency(0.01*u.T, particle='T+', to_hz=True)
    <Quantity 50923.9... Hz>
    >>> omega_ce = gyrofrequency(0.1*u.T)
    >>> print(omega_ce)
    1758820... rad / s
    >>> f_ce = omega_ce.to(u.Hz, equivalencies=[(u.cy/u.s, u.Hz)])
    >>> print(f_ce)
    279924... Hz

    """
    m_i = particles.particle_mass(particle)
    Z = _grab_charge(particle, Z)
    if not signed:
        Z = abs(Z)

    omega_ci = u.rad * (Z * e * np.abs(B) / m_i).to(1 / u.s)

    return omega_ci
Пример #7
0
def thermal_speed(
    T: u.K,
    particle: particles.Particle = "e-",
    method="most_probable",
    mass: u.kg = np.nan * u.kg,
) -> u.m / u.s:
    r"""
    Return the most probable speed for a particle within a Maxwellian
    distribution.

    Parameters
    ----------
    T : ~astropy.units.Quantity
        The particle temperature in either kelvin or energy per particle

    particle : str, optional
        Representation of the particle species (e.g., `'p'` for protons, `'D+'`
        for deuterium, or `'He-4 +1'` for singly ionized helium-4),
        which defaults to electrons.  If no charge state information is
        provided, then the particles are assumed to be singly charged.

    method : str, optional
        Method to be used for calculating the thermal speed. Options are
        `'most_probable'` (default), `'rms'`, and `'mean_magnitude'`.

    mass : ~astropy.units.Quantity
        The particle's mass override. Defaults to NaN and if so, doesn't do
        anything, but if set, overrides mass acquired from `particle`. Useful
        with relative velocities of particles.

    Returns
    -------
    V : ~astropy.units.Quantity
        particle thermal speed

    Raises
    ------
    TypeError
        The particle temperature is not a ~astropy.units.Quantity

    ~astropy.units.UnitConversionError
        If the particle temperature is not in units of temperature or
        energy per particle

    ValueError
        The particle temperature is invalid or particle cannot be used to
        identify an isotope or particle

    Warns
    -----
    RelativityWarning
        If the ion sound speed exceeds 5% of the speed of light, or

    ~astropy.units.UnitsWarning
        If units are not provided, SI units are assumed.

    Notes
    -----
    The particle thermal speed is given by:

    .. math::
        V_{th,i} = \sqrt{\frac{2 k_B T_i}{m_i}}

    This function yields the most probable speed within a distribution
    function.  However, the definition of thermal velocity varies by
    the square root of two depending on whether or not this velocity
    absorbs that factor in the expression for a Maxwellian
    distribution.  In particular, the expression given in the NRL
    Plasma Formulary [1] is a square root of two smaller than the
    result from this function.

    Examples
    --------
    >>> from astropy import units as u
    >>> thermal_speed(5*u.eV, 'p')
    <Quantity 30949.6... m / s>
    >>> thermal_speed(1e6*u.K, particle='p')
    <Quantity 128486... m / s>
    >>> thermal_speed(5*u.eV, particle='e-')
    <Quantity 132620... m / s>
    >>> thermal_speed(1e6*u.K, particle='e-')
    <Quantity 550569... m / s>
    >>> thermal_speed(1e6*u.K, method="rms")
    <Quantity 674307... m / s>
    >>> thermal_speed(1e6*u.K, method="mean_magnitude")
    <Quantity 621251... m / s>

    """
    m = mass if np.isfinite(mass) else particles.particle_mass(particle)

    # different methods, as per https://en.wikipedia.org/wiki/Thermal_velocity
    if method == "most_probable":
        V = np.sqrt(2 * k_B * T / m)
    elif method == "rms":
        V = np.sqrt(3 * k_B * T / m)
    elif method == "mean_magnitude":
        V = np.sqrt(8 * k_B * T / (m * np.pi))
    else:
        raise ValueError("Method {method} not supported in thermal_speed")

    return V
Пример #8
0
def ion_sound_speed(
    T_e: u.K,
    T_i: u.K,
    n_e: u.m**-3 = None,
    k: u.m**-1 = None,
    gamma_e=1,
    gamma_i=3,
    ion="p+",
    z_mean=None,
) -> u.m / u.s:
    r"""
    Return the ion sound speed for an electron-ion plasma.

    Parameters
    ----------
    T_e : ~astropy.units.Quantity
        Electron temperature in units of temperature or energy per
        particle. If this is not given, then the electron temperature
        is assumed to be zero.

    T_i : ~astropy.units.Quantity
        Ion temperature in units of temperature or energy per
        particle.  If this is not given, then the ion temperature is
        assumed to be zero.

    n_e : ~astropy.units.Quantity
        Electron number density. If this is not given, then ion_sound_speed
        will be approximated in the non-dispersive limit
        (:math:`k^2 \lambda_{D}^2` will be assumed zero). If n_e is given,
        a value for k must also be given.

    k : ~astropy.units.Quantity
        Wavenumber (in units of inverse length, e.g. per meter). If this
        is not given, then ion_sound_speed will be approximated in the
        non-dispersive limit (:math:`k^2 \lambda_{D}^2` will be assumed zero).
        If k is given, a value for n_e must also be given.

    gamma_e : float or int
        The adiabatic index for electrons, which defaults to 1.  This
        value assumes that the electrons are able to equalize their
        temperature rapidly enough that the electrons are effectively
        isothermal.

    gamma_i : float or int
        The adiabatic index for ions, which defaults to 3.  This value
        assumes that ion motion has only one degree of freedom, namely
        along magnetic field lines.

    ion : str, optional
        Representation of the ion species (e.g., `'p'` for protons,
        `'D+'` for deuterium, or 'He-4 +1' for singly ionized
        helium-4), which defaults to protons.  If no charge state
        information is provided, then the ions are assumed to be
        singly charged.

    z_mean : ~astropy.units.Quantity, optional
        The average ionization (arithmetic mean) for a plasma where the
        a macroscopic description is valid. If this quantity is not
        given then the atomic charge state (integer) of the ion
        is used. This is effectively an average ion sound speed for the
        plasma where multiple charge states are present.

    Returns
    -------
    V_S : ~astropy.units.Quantity
        The ion sound speed in units of meters per second.

    Raises
    ------
    TypeError
        If any of the arguments are not entered as keyword arguments
        or are of an incorrect type.

    ValueError
        If the ion mass, adiabatic index, or temperature are invalid.

    ~plasmapy.utils.PhysicsError
        If an adiabatic index is less than one.

    ~astropy.units.UnitConversionError
        If the temperature, electron number density, or wavenumber
        is in incorrect units.

    Warns
    -----
    RelativityWarning
        If the ion sound speed exceeds 5% of the speed of light.

    ~astropy.units.UnitsWarning
        If units are not provided, SI units are assumed.

    PhysicsWarning
        If only one of (k, n_e) is given, the non-dispersive limit
        is assumed.

    Notes
    -----
    The ion sound speed :math:`V_S` is given by

    .. math::

        V_S = \sqrt{\frac{\gamma_e Z k_B T_e + \gamma_i k_B T_i}{m_i (1 + k^2 \lambda_{D}^2)}}

    where :math:`\gamma_e` and :math:`\gamma_i` are the electron and
    ion adiabatic indices, :math:`k_B` is the Boltzmann constant,
    :math:`T_e` and :math:`T_i` are the electron and ion temperatures,
    :math:`Z` is the charge state of the ion, :math:`m_i` is the
    ion mass, :math:`\lambda_{D}` is the Debye length, and :math:`k` is the
    wavenumber.

    In the non-dispersive limit (:math:`k^2 \lambda_{D}^2` is small) the
    equation for :math:`V_S` is approximated (the denominator reduces
    to :math:`m_i`).

    When the electron temperature is much greater than the ion
    temperature, the ion sound velocity reduces to
    :math:`\sqrt{\gamma_e k_B T_e / m_i}`. Ion acoustic waves can
    therefore occur even when the ion temperature is zero.

    Example
    -------
    >>> from astropy import units as u
    >>> n = 5e19*u.m**-3
    >>> k_1 = 3e1*u.m**-1
    >>> k_2 = 3e7*u.m**-1
    >>> ion_sound_speed(T_e=5e6*u.K, T_i=0*u.K, ion='p', gamma_e=1, gamma_i=3)
    <Quantity 203155... m / s>
    >>> ion_sound_speed(T_e=5e6*u.K, T_i=0*u.K, n_e=n, k=k_1, ion='p', gamma_e=1, gamma_i=3)
    <Quantity 203155... m / s>
    >>> ion_sound_speed(T_e=5e6*u.K, T_i=0*u.K, n_e=n, k=k_2, ion='p', gamma_e=1, gamma_i=3)
    <Quantity 310.31... m / s>
    >>> ion_sound_speed(T_e=5e6*u.K, T_i=0*u.K, n_e=n, k=k_1)
    <Quantity 203155... m / s>
    >>> ion_sound_speed(T_e=500*u.eV, T_i=200*u.eV, n_e=n, k=k_1, ion='D+')
    <Quantity 229585... m / s>

    """

    m_i = particles.particle_mass(ion)
    Z = _grab_charge(ion, z_mean)

    for gamma, species in zip([gamma_e, gamma_i], ["electrons", "ions"]):
        if not isinstance(gamma, (numbers.Real, numbers.Integral)):
            raise TypeError(
                f"The adiabatic index gamma for {species} must be a float or int"
            )
        if gamma < 1:
            raise PhysicsError(
                f"The adiabatic index for {species} must be between "
                f"one and infinity")

    # Assume non-dispersive limit if values for n_e (or k) are not specified
    klD2 = 0.0
    if (n_e is None) ^ (k is None):
        warnings.warn(
            "The non-dispersive limit has been assumed for "
            "this calculation. To prevent this, values must "
            "be specified for both n_e and k.",
            PhysicsWarning,
        )
    elif n_e is not None and k is not None:
        lambda_D = Debye_length(T_e, n_e)
        klD2 = (k * lambda_D)**2

    try:
        V_S_squared = (gamma_e * Z * k_B * T_e +
                       gamma_i * k_B * T_i) / (m_i * (1 + klD2))
        V_S = np.sqrt(V_S_squared).to(u.m / u.s)
    except Exception:
        raise ValueError("Unable to find ion sound speed.")

    return V_S
Пример #9
0
def plasma_frequency(n: u.m**-3, particle="e-", z_mean=None) -> u.rad / u.s:
    r"""Calculate the particle plasma frequency.

    Parameters
    ----------
    n : ~astropy.units.Quantity
        Particle number density in units convertible to per cubic meter

    particle : str, optional
        Representation of the particle species (e.g., 'p' for protons, 'D+'
        for deuterium, or 'He-4 +1' for singly ionized helium-4),
        which defaults to electrons.  If no charge state information is
        provided, then the particles are assumed to be singly charged.

    z_mean : ~astropy.units.Quantity, optional
        The average ionization (arithmetic mean) for a plasma where the
        a macroscopic description is valid. If this quantity is not
        given then the atomic charge state (`int`) of the ion
        is used. This is effectively an average plasma frequency for the
        plasma where multiple charge states are present.

    Returns
    -------
    omega_p : ~astropy.units.Quantity
        The particle plasma frequency in radians per second.

    Raises
    ------
    TypeError
        If n_i is not a `~astropy.units.Quantity` or particle is not of
        an appropriate type.

    UnitConversionError
        If `n_i` is not in correct units

    ValueError
        If `n_i` contains invalid values or particle cannot be used to
        identify an particle or isotope.

    Warns
    -----
    ~astropy.units.UnitsWarning
        If units are not provided, SI units are assumed

    Notes
    -----
    The particle plasma frequency is

    .. math::
        \omega_{pi} = Z e \sqrt{\frac{n_i}{\epsilon_0 m_i}}

    At present, astropy.units does not allow direct conversions from
    radians/second for angular frequency to 1/second or Hz for
    frequency.  The dimensionless_angles equivalency allows that
    conversion, but does not account for the factor of 2*pi. The
    alternatives are to convert to cycle/second or to do the
    conversion manually, as shown in the examples.

    Example
    -------
    >>> from astropy import units as u
    >>> plasma_frequency(1e19*u.m**-3, particle='p')
    <Quantity 4.16329...e+09 rad / s>
    >>> plasma_frequency(1e19*u.m**-3, particle='p', to_hz=True)
    <Quantity 6.62608...e+08 Hz>
    >>> plasma_frequency(1e19*u.m**-3, particle='D+')
    <Quantity 2.94462...e+09 rad / s>
    >>> plasma_frequency(1e19*u.m**-3)
    <Quantity 1.78398...e+11 rad / s>
    >>> plasma_frequency(1e19*u.m**-3, to_hz=True)
    <Quantity 2.83930...e+10 Hz>

    """

    try:
        m = particles.particle_mass(particle)
        if z_mean is None:
            # warnings.warn("No z_mean given, defaulting to atomic charge",
            #               PhysicsWarning)
            try:
                Z = particles.integer_charge(particle)
            except Exception:
                Z = 1
        else:
            # using user provided average ionization
            Z = z_mean
        Z = np.abs(Z)
        # TODO REPLACE WITH Z = np.abs(_grab_charge(particle, z_mean)), some bugs atm
    except Exception:
        raise ValueError(f"Invalid particle, {particle}, in plasma_frequency.")

    omega_p = u.rad * Z * e * np.sqrt(n / (eps0 * m))

    return omega_p.si
Пример #10
0
def thermal_speed(
    T: u.K,
    particle: Particle,
    method="most_probable",
    mass: u.kg = None,
    ndim=3,
) -> u.m / u.s:
    r"""
    Calculate the speed of thermal motion for particles with a Maxwellian
    distribution.  (See the :ref:`Notes <thermal-speed-notes>` section for
    details.)

    **Aliases:** `~plasmapy.formulary.speeds.vth_`

    **Lite Version:** `~plasmapy.formulary.speeds.thermal_speed_lite`

    Parameters
    ----------
    T : `~astropy.units.Quantity`
        The temperature of the particle distribution, in units of kelvin or
        energy.

    particle : `~plasmapy.particles.particle_class.Particle`
        Representation of the particle species (e.g., ``"p"`` for protons,
        ``"D+"`` for deuterium, or ``"He-4 +1"`` for singly ionized helium-4).
        If no charge state information is provided, then the particles are
        assumed to be singly charged.

    method : `str`, optional
        (Default ``"most_probable"``) Method to be used for calculating the
        thermal speed. Valid values are ``"most_probable"``, ``"rms"``,
        ``"mean_magnitude"``, and ``"nrl"``.

    mass : `~astropy.units.Quantity`
        Mass override in units convertible to kg.  If given, then ``mass`` will
        be used instead of the mass value associated with ``particle``.

    ndim : `int`
        (Default ``3``) Dimensionality (1D, 2D, 3D) of space in which to
        calculate thermal speed. Valid values are ``1``, ``2``, or ``3``.

    Returns
    -------
    vth : `~astropy.units.Quantity`
        Thermal speed of the Maxwellian distribution.

    Raises
    ------
    `TypeError`
        The particle temperature is not a `~astropy.units.Quantity`.

    `~astropy.units.UnitConversionError`
        If the particle temperature is not in units of temperature or
        energy per particle.

    `ValueError`
        The particle temperature is invalid or particle cannot be used to
        identify an isotope or particle.

    Warns
    -----
    : `~plasmapy.utils.exceptions.RelativityWarning`
        If the ion sound speed exceeds 5% of the speed of light.

    : `~astropy.units.UnitsWarning`
        If units are not provided, SI units are assumed.


    .. _thermal-speed-notes:

    Notes
    -----

    There are multiple methods (or definitions) for calculating the thermal
    speed, all of which give the expression

    .. math::
        v_{th} = C_o \sqrt{\frac{k_B T}{m}}

    where :math:`T` is the temperature associated with the distribution,
    :math:`m` is the particle's mass, and :math:`C_o` is a constant of
    proportionality determined by the method in which :math:`v_{th}` is
    calculated and the dimensionality of the system (1D, 2D, 3D).  The
    :math:`C_o` used for the ``thermal_speed`` calculation is determined from
    the input arguments ``method`` and ``ndim``, and the values can be seen in
    the table below:

    .. table:: Values for :math:`C_o`
       :widths: 2 1 1 1 1
       :width: 100%

       +--------------+------------+---------------+---------------+---------------+
       | ↓ **method** | **ndim** → | ``1``         | ``2``         | ``3``         |
       +--------------+------------+---------------+---------------+---------------+
       | ``"most_probable"``       | .. math::     | .. math::     | .. math::     |
       |                           |    0          |    1          |    \sqrt{2}   |
       +--------------+------------+---------------+---------------+---------------+
       | ``"rms"``                 | .. math::     | .. math::     | .. math::     |
       |                           |    1          |    \sqrt{2}   |    \sqrt{3}   |
       +--------------+------------+---------------+---------------+---------------+
       | ``"mean_magnitude"``      | .. math::     | .. math::     | .. math::     |
       |                           |    \sqrt{2/π} |    \sqrt{π/2} |    \sqrt{8/π} |
       +--------------+------------+---------------+---------------+---------------+
       | ``"nrl"``                 | .. math::                                     |
       |                           |    1                                          |
       +--------------+------------+---------------+---------------+---------------+

    The coefficients can be directly retrieved using
    `~plasmapy.formulary.speeds.thermal_speed_coefficients`.

        .. rubric:: The Methods

        In the following discussion the Maxwellian distribution
        :math:`f(\mathbf{v})` is assumed to be 3D, but similar expressions can
        be given for 1D and 2D.

        - **Most Probable** ``method = "most_probable"``

          This method expresses the thermal speed of the distribution by expressing
          it as the most probable speed a particle in the distribution may have.
          To do this we first define another function :math:`g(v)` given by

          .. math::
             \int_{0}^{\infty} g(v) dv
                = \int_{-\infty}^{\infty} f(\mathbf{v}) d^3\mathbf{v}
                \quad \rightarrow \quad
                g(v) = 4 \pi v^2 f(v)

          then

          .. math::
             g^{\prime}(v_{th}) = \left.\frac{dg}{dv}\right|_{v_{th}} = 0\\
             \implies v_{th} = \sqrt{\frac{2 k_B T}{m}}

        - **Root Mean Square** ``method = "rms"``

          This method uses the root mean square to calculate an expression for
          the thermal speed of the particle distribution, which is given by

          .. math::
             v_{th} = \left[\int v^2 f(\mathbf{v}) d^3 \mathbf{v}\right]^{1/2}
                        = \sqrt{\frac{3 k_B T}{m}}

        - **Mean Magnitude** ``method = "mean_magnitude"``

          This method uses the mean speed of the particle distribution to
          calculate an expression for the thermal speed, which is given by

          .. math::
             v_{th} = \int |\mathbf{v}| f(\mathbf{v}) d^3 \mathbf{v}
                         = \sqrt{\frac{8 k_B T}{\pi m}}


        - **NRL Formulary** ``method = "nrl"``

          The NRL Plasma Formulary :cite:p:`nrlformulary:2019`
          uses the square root of the Normal distribution's variance
          as the expression for thermal speed.

          .. math::
             v_{th} = σ = \sqrt{\frac{k_B T}{m}} \quad
             \text{where} \quad f(v) \sim e^{v^2 / 2 σ^2}

    Examples
    --------
    >>> from astropy import units as u
    >>> thermal_speed(5*u.eV, 'p')
    <Quantity 30949.6... m / s>
    >>> thermal_speed(1e6*u.K, particle='p')
    <Quantity 128486... m / s>
    >>> thermal_speed(5*u.eV, particle='e-')
    <Quantity 132620... m / s>
    >>> thermal_speed(1e6*u.K, particle='e-')
    <Quantity 550569... m / s>
    >>> thermal_speed(1e6*u.K, "e-", method="rms")
    <Quantity 674307... m / s>
    >>> thermal_speed(1e6*u.K, "e-", method="mean_magnitude")
    <Quantity 621251... m / s>

    For user convenience `~plasmapy.formulary.speeds.thermal_speed_coefficients`
    and `~plasmapy.formulary.speeds.thermal_speed_lite` are bound to this function
    and can be used as follows.

    >>> from plasmapy.particles import Particle
    >>> mass = Particle("p").mass.value
    >>> coeff = thermal_speed.coefficients(method="most_probable", ndim=3)
    >>> thermal_speed.lite(T=1e6, mass=mass, coeff=coeff)
    128486...
    """
    if mass is None:
        mass = particle_mass(particle)

    coeff = thermal_speed_coefficients(method=method, ndim=ndim)

    speed = thermal_speed_lite(T=T.value, mass=mass.value, coeff=coeff)
    return speed * u.m / u.s
Пример #11
0
def plasma_frequency(n: u.m**-3,
                     particle: Particle,
                     z_mean=None) -> u.rad / u.s:
    r"""Calculate the particle plasma frequency.

    **Aliases:** `wp_`

    **Lite Version:** `~plasmapy.formulary.frequencies.plasma_frequency_lite`

    Parameters
    ----------
    n : `~astropy.units.Quantity`
        Particle number density in units convertible to m\ :sup:`-3`.

    particle : `~plasmapy.particles.particle_class.Particle`
        Representation of the particle species (e.g., ``"p"`` for
        protons, ``"D+"`` for deuterium, or ``"He-4 +1"`` for singly
        ionized helium-4). If no charge state information is provided,
        then the particles are assumed to be singly charged.

    z_mean : `~numbers.Real`, optional
        The average ionization (arithmetic mean) for the particle
        species in the plasma.  Typically, the charge state will be
        derived from the ``particle`` argument, but this keyword will
        override that behavior.

    Returns
    -------
    omega_p : `~astropy.units.Quantity`
        The particle plasma frequency in radians per second.  Setting
        keyword ``to_hz=True`` will apply the factor of :math:`1/2π`
        and yield a value in Hz.

    Raises
    ------
    `TypeError`
        If ``n`` is not a `~astropy.units.Quantity` or particle is not
        of an appropriate type.

    `~astropy.units.UnitConversionError`
        If ``n`` is not in correct units.

    `ValueError`
        If ``n`` contains invalid values or particle cannot be used to
        identify a particle or isotope.

    Warns
    -----
    : `~astropy.units.UnitsWarning`
        If units are not provided, SI units are assumed.

    Notes
    -----
    The particle plasma frequency is

    .. math::
        ω_{p} = Z |e| \sqrt{\frac{n}{\epsilon_0 m}}

    where :math:`m` is the mass of the particle, :math:`e` is the
    fundamental unit of charge, :math:`Z` is the average charge state
    ``z_mean`` of the particle species, :math:`n` is the particle number
    density.  This form of the plasma frequency has units of
    radians / s, but using the ``to_hz`` will apply the factor of
    :math:`1/2π` to give a value in Hz.

    Examples
    --------
    >>> from astropy import units as u
    >>> plasma_frequency(1e19*u.m**-3, particle='p')
    <Quantity 4.16329...e+09 rad / s>
    >>> plasma_frequency(1e19*u.m**-3, particle='p', to_hz=True)
    <Quantity 6.62608...e+08 Hz>
    >>> plasma_frequency(1e19*u.m**-3, particle='D+')
    <Quantity 2.94462...e+09 rad / s>
    >>> plasma_frequency(1e19*u.m**-3, 'e-')
    <Quantity 1.78398...e+11 rad / s>
    >>> plasma_frequency(1e19*u.m**-3, 'e-', to_hz=True)
    <Quantity 2.83930...e+10 Hz>

    For user convenience
    `~plasmapy.formulary.frequencies.plasma_frequency_lite` is bound to
    this function and can be used as follows.

    >>> from plasmapy.particles import Particle
    >>> mass = Particle("p").mass.value
    >>> plasma_frequency.lite(n=1e19, mass=mass, z_mean=1)
    416329...
    >>> plasma_frequency.lite(n=1e19, mass=mass, z_mean=1, to_hz=True)
    662608...
    """

    try:
        m = particles.particle_mass(particle).value

        if z_mean is None:
            # warnings.warn("No z_mean given, defaulting to atomic charge",
            #               PhysicsWarning)
            try:
                Z = particles.charge_number(particle)
            except ChargeError:
                Z = 1
        else:
            # using user provided average ionization
            Z = z_mean
        Z = np.abs(Z)
        # TODO REPLACE WITH Z = np.abs(_grab_charge(particle, z_mean)), some bugs atm
    except InvalidParticleError as e:
        raise ValueError(
            f"Invalid particle, {particle}, in plasma_frequency.") from e

    return plasma_frequency_lite(n=n, mass=m, z_mean=Z) * u.rad / u.s