Exemple #1
0
    def test_hollweg1999_vals(self, kwargs, expected, desired_beta):
        """
        Test calculated values based on Figure 2 of Hollweg1999
        (DOI: https://doi.org/10.1029/1998JA900132) using eqn 3 of
        Bellan 2012
        (DOI: https://doi.org/10.1029/2012JA017856).

        The WebPlotDigitizer software was used to determine the test
        parameters for k, B, and expected omega from Figure 2 of
        Hollweg1999.

        - GitHub: https://github.com/ankitrohatgi/WebPlotDigitizer
        - Web Version: https://automeris.io/WebPlotDigitizer/
        """
        # k values need to be single valued for this test to function correctly

        cs = speeds.cs_(kwargs["T_e"], kwargs["T_i"], kwargs["ion"]).value
        va = speeds.va_(kwargs["B"], kwargs["n_i"], ion=kwargs["ion"]).value

        beta = (cs / va)**2
        if not np.isclose(beta, desired_beta, atol=2e-4):
            pytest.fail(
                f"The Holweg 1999 paper requires a 'beta' value of {desired_beta:0.5f} "
                f"and the test parameters yielded {beta:.6f}.")

        kz = (np.cos(kwargs["theta"]) * kwargs["k"]).value

        w_alfven = (hollweg(**kwargs)["alfven_mode"]).value
        big_omega = np.abs(w_alfven / (kz * va))

        assert np.allclose(big_omega, expected, atol=1e-2)
    def test_on_bellan2012_vals(self, kwargs, expected):
        """
        Test calculated values based on Figure 1 of Bellan 2012
        (DOI: https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2012JA017856).
        """
        # theta and k values need to be single valued for this test to function
        # correctly

        cs = cs_(kwargs["T_e"], kwargs["T_i"], kwargs["ion"])
        va = va_(kwargs["B"], kwargs["n_i"], ion=kwargs["ion"])
        wci = wc_(kwargs["B"], kwargs["ion"])

        beta = (cs / va).value**2
        if not np.isclose(beta, 0.4, atol=1e-4):
            pytest.fail(
                f"The Bellan 2012 paper requires a 'beta' value of 0.4 and the test "
                f"parameters yielded {beta:.6f}.")

        Lambda = (kwargs["k"] * va / wci).value**2
        if not np.isclose(Lambda, 0.4, atol=1e-4):
            pytest.fail(
                f"The Bellan 2012 paper requires a 'Lambda' value of 0.4 and the test "
                f"parameters yielded {Lambda:.6f}.")

        ws = two_fluid(**kwargs)
        for mode, val in ws.items():
            norm = (np.absolute(val) / (kwargs["k"] * va)).value**2
            assert np.isclose(norm, expected[mode])
Exemple #3
0
class TestAlfvenSpeed:
    """Test `~plasmapy.formulary.speeds.Alfven_speed`."""

    @pytest.mark.parametrize(
        "args, kwargs, _error",
        [
            # scenarios that raise RelativityError
            ((10 * u.T, 1.0e-10 * u.kg * u.m ** -3), {}, RelativityError),
            ((np.inf * u.T, 1 * u.m ** -3), {"ion": "p"}, RelativityError),
            ((-np.inf * u.T, 1 * u.m ** -3), {"ion": "p"}, RelativityError),
            #
            # scenarios that raise InvalidParticleError
            ((1 * u.T, 5e19 * u.m ** -3), {"ion": "spacecats"}, InvalidParticleError),
            #
            # scenarios that raise TypeError
            (("not a Bfield", 1.0e-10 * u.kg * u.m ** -3), {}, TypeError),
            ((10 * u.T, "not a density"), {}, TypeError),
            ((10 * u.T, 5), {"ion": "p"}, TypeError),
            ((1 * u.T, 1.0e18 * u.m ** -3), {"ion": ["He"]}, TypeError),
            ((1 * u.T, 1.0e18 * u.m ** -3), {"ion": "He", "z_mean": "nope"}, TypeError),
            #
            # scenarios that raise UnitTypeError
            ((1 * u.T, 1.0e18 * u.cm), {"ion": "He"}, u.UnitTypeError),
            ((1 * u.T, 5 * u.m ** -2), {"ion": "p"}, u.UnitTypeError),
            ((1 * u.cm, 1.0e18 * u.m ** -3), {"ion": "He"}, u.UnitTypeError),
            ((5 * u.A, 5e19 * u.m ** -3), {"ion": "p"}, u.UnitTypeError),
            #
            # scenarios that raise ValueError
            ((1 * u.T, -1.0e18 * u.m ** -3), {"ion": "He"}, ValueError),
            (
                (np.array([5, 6, 7]) * u.T, np.array([5, 6]) * u.m ** -3),
                {"ion": "p"},
                ValueError,
            ),
            (
                (np.array([0.001, 0.002]) * u.T, np.array([-5e19, 6e19]) * u.m ** -3),
                {"ion": "p"},
                ValueError,
            ),
        ],
    )
    def test_raises(self, args, kwargs, _error):
        """Test scenarios that raise exceptions or warnings."""
        with pytest.raises(_error):
            Alfven_speed(*args, **kwargs)

    @pytest.mark.parametrize(
        "args, kwargs, expected, isclose_kw, _warning",
        [
            # scenarios that issue RelativityWarning
            (
                (5 * u.T, 5e19 * u.m ** -3),
                {"ion": "H"},
                15413707.39,
                {},
                RelativityWarning,
            ),
            (
                (5 * u.T, 5e19 * u.m ** -3),
                {"ion": "H+"},
                15413707.39,
                {"rtol": 3.0e-4},
                RelativityWarning,
            ),
            (
                (5 * u.T, 5e19 * u.m ** -3),
                {"ion": "p"},
                15413707.39,
                {"rtol": 4.0e-4},
                RelativityWarning,
            ),
            #
            # scenarios that issue UnitsWarning
            ((0.5, 1.0e18 * u.m ** -3), {"ion": "He"}, 5470657.93, {}, u.UnitsWarning),
        ],
    )
    def test_warns(self, args, kwargs, expected, isclose_kw, _warning):
        """Test scenarios that issue warnings"""
        with pytest.warns(_warning):
            val = Alfven_speed(*args, **kwargs)
            assert isinstance(val, u.Quantity)
            assert val.unit == u.m / u.s
            assert np.isclose(val.value, expected, **isclose_kw)

    @pytest.mark.parametrize(
        "args, kwargs, expected, isclose_kw",
        [
            (
                (1 * u.T, 1e-8 * u.kg * u.m ** -3),
                {"ion": "p"},
                8920620.58 * u.m / u.s,
                {"rtol": 1e-6},
            ),
            (
                (1 * u.T, 1e-8 * u.kg * u.m ** -3),
                {},
                8920620.58 * u.m / u.s,
                {"rtol": 1e-6},
            ),
            (
                (0.05 * u.T, 1e18 * u.m ** -3),
                {"ion": "He"},
                Alfven_speed(0.05 * u.T, 6.64738793e-09 * u.kg * u.m ** -3),
                {},
            ),
            (
                (0.05 * u.T, 1e18 * u.m ** -3),
                {"ion": "He+"},
                Alfven_speed(0.05 * u.T, 1e18 * u.m ** -3, ion="He"),
                {"rtol": 7e-5},
            ),
            (
                (0.05 * u.T, 1e18 * u.m ** -3),
                {"ion": "He", "z_mean": 2},
                Alfven_speed(0.05 * u.T, 1e18 * u.m ** -3, ion="He +2"),
                {"rtol": 1.4e-4},
            ),
            (
                (0.05 * u.T, 1e18 * u.m ** -3),
                {"ion": Particle("He+")},
                Alfven_speed(0.05 * u.T, 1e18 * u.m ** -3, ion="He+"),
                {},
            ),
            (
                ([0.001, 0.002] * u.T, 5e-10 * u.kg * u.m ** -3),
                {},
                [
                    va_(0.001 * u.T, 5e-10 * u.kg * u.m ** -3).value,
                    va_(0.002 * u.T, 5e-10 * u.kg * u.m ** -3).value,
                ]
                * (u.m / u.s),
                {},
            ),
            (
                ([0.001, 0.002] * u.T, [5e-10, 2e-10] * u.kg * u.m ** -3),
                {},
                [
                    va_(0.001 * u.T, 5e-10 * u.kg * u.m ** -3).value,
                    va_(0.002 * u.T, 2e-10 * u.kg * u.m ** -3).value,
                ]
                * (u.m / u.s),
                {},
            ),
            (
                (0.001 * u.T, [1.0e18, 2e18] * u.m ** -3),
                {"ion": "p"},
                [
                    va_(0.001 * u.T, 1e18 * u.m ** -3, ion="p").value,
                    va_(0.001 * u.T, 2e18 * u.m ** -3, ion="p").value,
                ]
                * (u.m / u.s),
                {},
            ),
        ],
    )
    def test_values(self, args, kwargs, expected, isclose_kw):
        """Test expected values."""
        assert np.allclose(Alfven_speed(*args, **kwargs), expected, **isclose_kw)

    @pytest.mark.parametrize(
        "args, kwargs, nan_mask",
        [
            ((np.nan * u.T, 1 * u.kg * u.m ** -3), {}, []),
            ((0.001 * u.T, np.nan * u.kg * u.m ** -3), {}, []),
            (([np.nan, 0.001] * u.T, 1 * u.kg * u.m ** -3), {}, [True, False]),
            (
                (0.001 * u.T, [np.nan, 1.0, np.nan] * u.kg * u.m ** -3),
                {},
                [True, False, True],
            ),
            (([np.nan, 0.001] * u.T, [1, np.nan] * u.kg * u.m ** -3), {}, [True, True]),
            (
                (0.001 * u.T, [np.nan, 1e18, np.nan] * u.m ** -3),
                {"ion": "Ar+"},
                [True, False, True],
            ),
        ],
    )
    def test_nan_values(self, args, kwargs, nan_mask):
        """Input scenarios that lead to `numpy.nan` values being returned."""
        val = Alfven_speed(*args, **kwargs)
        if np.isscalar(val.value):
            assert np.isnan(val)
        else:
            nan_arr = np.isnan(val)
            assert np.all(nan_arr[nan_mask])
            assert np.all(np.logical_not(nan_arr[np.logical_not(nan_mask)]))

    def test_handle_nparrays(self):
        """Test for ability to handle numpy array quantities"""
        assert_can_handle_nparray(Alfven_speed)