def test_plasma_dispersion_deriv_errors(self, w, expected_error): """Test errors that should be raised by plasma_dispersion_func_deriv.""" with pytest.raises(expected_error): plasma_dispersion_func_deriv(w) pytest.fail(f"plasma_dispersion_func_deriv({w}) did not raise " f"{expected_error.__name__} as expected.")
def test_plasma_dispersion_func_deriv_characterization(self, w): r"""Test plasma_dispersion_func_deriv against an exact relationship.""" # The exact analytical relationship comes from the bottom of # page 3 of Fried & Conte (1961). Z = plasma_dispersion_func(w) Z_deriv = plasma_dispersion_func_deriv(w) Z_deriv_characterization = -2 * (1 + w * Z) assert np.isclose(Z_deriv, Z_deriv_characterization, rtol=1e-15), ( f"The relationship that Z'(w) = -2 * [1 + w * Z(w)] is not " f"met for w = {w}, where Z'(w) = {Z_deriv} and " f"-2 * [1 + w * Z(w)] = {Z_deriv_characterization}.")
def test_plasma_dispersion_func_deriv(self, w, expected): r"""Test plasma_dispersion_func_deriv against tabulated results""" # The tabulated results are taken from Fried & Conte (1961) Z_deriv = plasma_dispersion_func_deriv(w) assert np.isclose( Z_deriv, expected, atol=5e-5 * (1 + 1j), rtol=5e-6 ), (f"The derivative of the plasma dispersion function does not match " f"the expected value for w = {w}. The value of " f"plasma_dispersion_func_deriv({w}) equals {Z_deriv} whereas the " f"expected value is {expected}. The difference between the actual " f"and expected results is {Z_deriv - expected}.")
def test_normal_vs_lite(self, w, expected): r"""Test that plasma_dispersion_func_deriv and plasma_dispersion_func_deriv_lite calculate the same values.""" # Many of the tabulated results originally came from the book # entitled "The Plasma Dispersion Function: The Hilbert Transform # of the Gaussian" by B. D. Fried and S. D. Conte (1961). Z_of_w = plasma_dispersion_func_deriv(w) Z_of_w_lite = plasma_dispersion_func_deriv_lite(w) assert np.isclose( Z_of_w, Z_of_w_lite, atol=1e-12 * (1 + 1j), rtol=1e-12), (f"plasma_dispersion_func_deriv({w}) and " "plasma_dispersion_func_deriv_lite({w}) " "are not equal.")
def test_plasma_dispersion_func_deriv(w, expected): r"""Test plasma_dispersion_func_deriv against tabulated results and an exact relationship.""" # The tabulated results are taken from Fried & Conte (1961). The # exact analytical relationship comes from the bottom of page 3 of # Fried & Conte (1961). Z_deriv = plasma_dispersion_func_deriv(w) assert np.isclose(Z_deriv, expected, atol=5e-5 * (1 + 1j), rtol=5e-6), ( f"The derivative of the plasma dispersion function does not match " f"the expected value for w = {w}. The value of " f"plasma_dispersion_func_deriv({w}) equals {Z_deriv} whereas the " f"expected value is {expected}. The difference between the actual " f"and expected results is {Z_deriv - expected}.") Z = plasma_dispersion_func(w) Z_deriv_characterization = -2 * (1 + w * Z) assert np.isclose(Z_deriv, Z_deriv_characterization, rtol=1e-15), ( f"The relationship that Z'(w) = -2 * [1 + w * Z(w)] is not " f"met for w = {w}, where Z'(w) = {Z_deriv} and " f"-2 * [1 + w * Z(w)] = {Z_deriv_characterization}.")
def permittivity_1D_Maxwellian( omega: u.rad / u.s, kWave: u.rad / u.m, T: u.K, n: u.m ** -3, particle, z_mean: u.dimensionless_unscaled = None, ) -> u.dimensionless_unscaled: r""" The classical dielectric permittivity for a 1D Maxwellian plasma. This function can calculate both the ion and electron permittivities. No additional effects are considered (e.g. magnetic fields, relativistic effects, strongly coupled regime, etc.) Parameters ---------- omega : ~astropy.units.Quantity The frequency in rad/s of the electromagnetic wave propagating through the plasma. kWave : ~astropy.units.Quantity The corresponding wavenumber, in rad/m, of the electromagnetic wave propagating through the plasma. This is often modulated by the dispersion of the plasma or by relativistic effects. See em_wave.py for ways to calculate this. T : ~astropy.units.Quantity The plasma temperature - this can be either the electron or the ion temperature, but should be consistent with density and particle. n : ~astropy.units.Quantity The plasma density - this can be either the electron or the ion density, but should be consistent with temperature and particle. particle : str The plasma particle species. z_mean : str The average ionization of the plasma. This is only required for calculating the ion permittivity. Returns ------- chi : ~astropy.units.Quantity The ion or the electron dielectric permittivity of the plasma. This is a dimensionless quantity. Notes ----- The dielectric permittivities for a Maxwellian plasma are described by the following equations [1]_ .. math:: \chi_e(k, \omega) = - \frac{\alpha_e^2}{2} Z'(x_e) \chi_i(k, \omega) = - \frac{\alpha_i^2}{2}\frac{Z}{} Z'(x_i) \alpha = \frac{\omega_p}{k v_{Th}} x = \frac{\omega}{k v_{Th}} :math:`chi_e` and :math:`chi_i` are the electron and ion permittivities respectively. :math:`Z'` is the derivative of the plasma dispersion function. :math:`\alpha` is the scattering parameter which delineates the difference between the collective and non-collective Thomson scattering regimes. :math:`x` is the dimensionless phase velocity of the EM wave propagating through the plasma. References ---------- .. [1] J. Sheffield, D. Froula, S. H. Glenzer, and N. C. Luhmann Jr, Plasma scattering of electromagnetic radiation: theory and measurement techniques. Chapter 5 Pg 106 (Academic press, 2010). Example ------- >>> from astropy import units as u >>> from numpy import pi >>> from astropy.constants import c >>> T = 30 * 11600 * u.K >>> n = 1e18 * u.cm**-3 >>> particle = 'Ne' >>> z_mean = 8 * u.dimensionless_unscaled >>> vTh = parameters.thermal_speed(T, particle, method="most_probable") >>> omega = 5.635e14 * 2 * pi * u.rad / u.s >>> kWave = omega / vTh >>> permittivity_1D_Maxwellian(omega, kWave, T, n, particle, z_mean) <Quantity -6.72809...e-08+5.76037...e-07j> """ # thermal velocity vTh = parameters.thermal_speed(T=T, particle=particle, method="most_probable") # plasma frequency wp = parameters.plasma_frequency(n=n, particle=particle, z_mean=z_mean) # scattering parameter alpha. # explicitly removing factor of sqrt(2) to be consistent with Froula alpha = np.sqrt(2) * (wp / (kWave * vTh)).to(u.dimensionless_unscaled) # The dimensionless phase velocity of the propagating EM wave. zeta = (omega / (kWave * vTh)).to(u.dimensionless_unscaled) chi = alpha ** 2 * (-1 / 2) * plasma_dispersion_func_deriv(zeta.value) return chi
Z_of_w_lite = plasma_dispersion_func_lite(w) assert np.isclose( Z_of_w, Z_of_w_lite, atol=1e-12 * (1 + 1j), rtol=1e-12 ), (f"plasma_dispersion_func({w}) and plasma_dispersion_func_lite({w}) " "are not equal.") # Array of expected values for plasma_dispersion_func_deriv # w, expected plasma_disp_deriv_table = [ (0, -2), (1, 0.152_318 - 1.304_10j), (1j, -0.484_257), (1.2 + 4.4j, -0.397_561e-1 - 0.217_392e-1j), (9j, plasma_dispersion_func_deriv(9j * u.dimensionless_unscaled)), (5.4 - 3.1j, 0.012_449_1 + 0.023_138_3j), (9.9 - 10j, 476.153 + 553.121j), (5 + 7j, -4.591_20e-3 - 0.012_610_4j), (4.5 - 10j, 0.260_153e37 - 0.211_814e37j), ] class TestPlasmaDispersionFunctionDeriv: """ Test class for `plasmapy.dispersion.plasma_dispersion_func_deriv`. Note: Testing of `plasma_dispersion_func_deriv_lite` is done in a separate test class. """ @pytest.mark.parametrize(