Ejemplo n.º 1
0
class TestLegendreExpansion:
    """
    Testing of spherical harmonics transform for 1D fields.
    """
    def setup_method(self):
        self.l_max = 2**np.random.randint(4, 8)
        self.m_max = 0
        self.n_lat = 4 * self.l_max
        self.n_lon = 1
        self.sht = SHT(self.l_max, self.m_max, self.n_lon, self.n_lat)
        self.lat_grid = np.linspace(0, np.pi, self.n_lat + 1)
        self.lat_grid = 0.5 * (self.lat_grid[1:] + self.lat_grid[:-1])
        self.lon_grid = np.linspace(0, 2.0 * np.pi, self.n_lon + 1)[:-1]

    def test_legendre_transform(self):
        """
        Tests the Legendre expansion by transforming a given Legendre polynomial
        and ensuring that only one component in the output is set.
        """
        l = np.random.randint(1, self.l_max)
        m = 0

        xx, yy = np.meshgrid(self.lat_grid, self.lon_grid, indexing="xy")
        zz = sph_harm(m, l, yy, xx)
        coeffs = self.sht.transform(zz.real)
        print(coeffs)

        assert np.sum(np.abs(coeffs) > 1e-6) == 1

    def test_legendre_transform_cmplx(self):
        """
        Test transforming from complex spatial field to spectral field and back to ensure
        that the input field is recovered.
        """
        l = np.random.randint(1, self.l_max)
        m = 0

        xx, yy = np.meshgrid(self.lat_grid, self.lon_grid, indexing="xy")
        zz = sph_harm(m, l, yy, xx)
        aa = self.sht.transform_cmplx(zz)
        zz_rec = self.sht.synthesize_cmplx(2.0 * self.sht.transform_cmplx(zz))

        assert np.all(np.isclose(2.0 * zz, zz_rec))

    def test_evaluate(self):
        """
        Test that evaluating the spectral representation reproduces the spatial
        input.
        """
        l = np.random.randint(1, self.l_max)
        m = 0

        xx, yy = np.meshgrid(self.lat_grid, self.lon_grid, indexing="xy")
        zz_ref = sph_harm(m, l, yy, xx)
        coeffs = self.sht.transform(zz_ref.real)
        points = xx.ravel()
        zz = self.sht.evaluate(coeffs, points)

        assert np.all(np.isclose(zz, zz_ref.real.ravel()))
Ejemplo n.º 2
0
class TestSHT:
    """
    Testing of spherical harmonics transform for non-degenrate 2D fields.
    """
    def setup_method(self):
        self.l_max = np.random.randint(20, 100)
        self.m_max = np.random.randint(10, self.l_max)
        self.m_max = self.l_max  #np.random.randint(10, self.l_max)

        self.n_lat = 4 * self.l_max
        self.n_lon = 4 * self.l_max
        self.sht = SHT(self.l_max, self.m_max, self.n_lon, self.n_lat)
        self.lat_grid = np.linspace(0, np.pi, self.n_lat + 1)
        self.lat_grid = 0.5 * (self.lat_grid[1:] + self.lat_grid[:-1])
        self.lon_grid = np.linspace(0, 2.0 * np.pi, self.n_lon + 1)[:-1]

    def test_latitude_grid(self):
        """
        Test that the SHT class returns the expected latitude grid (Gauss-Legendre).
        """
        lat_grid_ref = self.lat_grid
        lat_grid = self.sht.get_latitude_grid()
        assert np.all(np.isclose(lat_grid_ref, lat_grid))

    def test_colatitude_grid(self):
        """
        Test that the SHT class returns the expected co-latitude grid (Gauss-Legendre).
        """
        lat_grid_ref = np.cos(self.lat_grid)
        lat_grid = self.sht.get_colatitude_grid()
        assert np.all(np.isclose(lat_grid_ref, lat_grid))

    def test_spatial_to_spectral(self):
        """
        Test transform from spatial to spectral representation by transforming
        spherical harmonics and ensuring that the result contains only one
        significant component.
        """
        l = np.random.randint(1, self.l_max)
        m_max = min(self.m_max, l)
        m_max = l
        m = np.random.randint(-m_max, m_max)

        xx, yy = np.meshgrid(self.lat_grid, self.lon_grid, indexing="xy")
        zz = sph_harm(m, l, yy, xx)
        coeffs = self.sht.transform(zz.real)

        assert np.sum(np.abs(coeffs) > 1e-6) == 1

    def test_inverse_transform(self):
        """
        Test transforming from spatial field to spectral field and back to ensure
        that the input field is recovered.
        """
        l = np.random.randint(1, self.l_max)
        m_max = min(self.m_max, l)
        m_max = l
        m = np.random.randint(-m_max, m_max)

        xx, yy = np.meshgrid(self.lon_grid, self.lat_grid, indexing="ij")
        zz = sph_harm(m, l, xx, yy)
        coeffs = self.sht.synthesize(self.sht.transform(zz.real).ravel())
        assert np.all(np.isclose(zz.real, coeffs))

    def test_inverse_transform_cmplx(self):
        """
        Test transforming from spatial field to spectral field and back to ensure
        that the input field is recovered.
        """
        l = np.random.randint(1, self.l_max)
        m_max = l  #min(self.m_max, l)
        m = np.random.randint(-m_max, m_max)

        xx, yy = np.meshgrid(self.lon_grid, self.lat_grid, indexing="ij")
        zz = sph_harm(m, l, xx, yy)
        coeffs = self.sht.transform_cmplx(zz)
        zz_rec = self.sht.synthesize_cmplx(2.0 * coeffs)
        assert np.all(np.isclose(2.0 * zz, zz_rec))

    def test_evaluate(self):
        """
        Test that evaluating the spectral representation reproduces the spatial
        input.
        """
        l = np.random.randint(1, self.l_max)
        m_max = min(self.m_max, l)
        m_max = l
        m = np.random.randint(-m_max, m_max)

        xx, yy = np.meshgrid(self.lat_grid, self.lon_grid, indexing="xy")
        zz_ref = sph_harm(m, l, yy, xx)
        coeffs = self.sht.transform(zz_ref.real)
        points = np.stack([yy.ravel(), xx.ravel()], axis=-1)
        zz = self.sht.evaluate(coeffs, points)

        assert np.all(np.isclose(zz, zz_ref.real.ravel()))