Exemplo n.º 1
0
    def test_convert_points_to_sph(self):
        """Test convert random points to spherical based on atomic structure."""
        rad_pts = np.array([0.1, 0.5, 1])
        rad_wts = np.array([0.3, 0.4, 0.3])
        rad_grid = OneDGrid(rad_pts, rad_wts)
        center = np.random.rand(3)
        atgrid = AtomGrid(rad_grid, degrees=[7], center=center)
        points = np.random.rand(100, 3)
        calc_sph = atgrid.convert_cartesian_to_spherical(points)
        # compute ref result
        ref_coor = points - center
        # radius
        r = np.linalg.norm(ref_coor, axis=-1)
        # azimuthal
        theta = np.arctan2(ref_coor[:, 1], ref_coor[:, 0])
        # polar
        phi = np.arccos(ref_coor[:, 2] / r)
        assert_allclose(np.stack([r, theta, phi]).T, calc_sph)
        assert_equal(calc_sph.shape, (100, 3))

        # test single point
        point = np.random.rand(3)
        calc_sph = atgrid.convert_cartesian_to_spherical(point)
        ref_coor = point - center
        r = np.linalg.norm(ref_coor)
        theta = np.arctan2(ref_coor[1], ref_coor[0])
        phi = np.arccos(ref_coor[2] / r)
        assert_allclose(np.array([r, theta, phi]).reshape(-1, 3), calc_sph)
Exemplo n.º 2
0
    def test_spherical_average_of_spherical_harmonic(self):
        r"""Test spherical average of spherical harmonic is zero."""

        # construct helper function
        def func(sph_points):
            # Spherical harmonic of order 6 and magnetic 0
            r, phi, theta = sph_points.T
            return (np.sqrt(13) / (np.sqrt(np.pi) * 32) *
                    (231 * np.cos(theta)**6.0 - 315 * np.cos(theta)**4.0 +
                     105 * np.cos(theta)**2.0 - 5.0))

        # Construct Radial Grid and atomic grid with spherical harmonics of degree 10
        #   for all points.
        oned_grid = np.arange(0.0, 5.0, 0.001)
        rad = OneDGrid(oned_grid, np.ones(len(oned_grid)), (0, np.inf))
        atgrid = AtomGrid(rad, degrees=[10])
        spherical_pts = atgrid.convert_cartesian_to_spherical(atgrid.points)
        func_values = func(spherical_pts)

        spherical_avg = atgrid.spherical_average(func_values)

        # Test that the spherical average of a spherical harmonic is zero.
        numb_pts = 1000
        random_rad_pts = np.random.uniform(0.02, np.pi, size=(numb_pts, 3))
        spherical_avg2 = spherical_avg(random_rad_pts[:, 0])
        assert_allclose(spherical_avg2, 0.0, atol=1e-4)
Exemplo n.º 3
0
    def test_spherical_average_of_gaussian(self):
        r"""Test spherical average of a Gaussian (radial) function is itself and its integral."""

        # construct helper function
        def func(sph_points):
            return np.exp(-sph_points[:, 0]**2.0)

        # Construct Radial Grid and atomic grid with spherical harmonics of degree 10
        #   for all points.
        oned_grid = np.arange(0.0, 5.0, 0.001)
        rad = OneDGrid(oned_grid, np.ones(len(oned_grid)), (0, np.inf))
        atgrid = AtomGrid(rad, degrees=[5])
        spherical_pts = atgrid.convert_cartesian_to_spherical(atgrid.points)
        func_values = func(spherical_pts)

        spherical_avg = atgrid.spherical_average(func_values)

        # Test that the spherical average of a Gaussian is itself
        numb_pts = 1000
        random_rad_pts = np.random.uniform(0.0, 1.5, size=(numb_pts, 3))
        spherical_avg2 = spherical_avg(random_rad_pts[:, 0])
        func_vals = func(random_rad_pts)
        assert_allclose(spherical_avg2, func_vals, atol=1e-4)

        # Test the integral of spherical average is the integral of Gaussian e^(-x^2)e^(-y^2)...
        #   from -infinity to infinity which is equal to pi^(3/2)
        integral = (
            4.0 * np.pi *
            np.trapz(y=spherical_avg(oned_grid) * oned_grid**2.0, x=oned_grid))
        actual_integral = np.sqrt(np.pi)**3.0
        assert_allclose(actual_integral, integral)
Exemplo n.º 4
0
    def test_fitting_product_of_spherical_harmonic(self):
        r"""Test fitting the radial components of r**2 times spherical harmonic."""
        max_degree = 7  # Maximum degree
        rad = OneDGrid(np.linspace(0.0, 1.0, num=10), np.ones(10), (0, np.inf))
        atom_grid = AtomGrid(rad, degrees=[max_degree])
        max_degree = atom_grid.l_max
        spherical = atom_grid.convert_cartesian_to_spherical()

        spherical_harmonic = generate_real_spherical_harmonics(
            4,
            spherical[:, 1],
            spherical[:, 2]  # theta, phi points
        )
        # Test on the function r^2 * Y^1_3
        func_vals = spherical[:,
                              0]**2.0 * spherical_harmonic[(3 + 1)**2 + 1, :]
        # Fit radial components
        fit = atom_grid.radial_component_splines(func_vals)
        radial_pts = np.arange(0.0, 1.0, 0.01)
        i = 0
        for l_value in range(0, max_degree // 2):
            for m in ([0] + [x for x in range(1, l_value + 1)] +
                      [x for x in range(-l_value, 0)]):
                if i != (3 + 1)**2 + 1:
                    assert_almost_equal(fit[i](radial_pts), 0.0, decimal=8)
                else:
                    # Test that on the right spherical harmonic the function r* Y^1_3 projects
                    # to \rho^{1,3}(r) = r
                    assert_almost_equal(fit[i](radial_pts), radial_pts**2.0)
                i += 1
Exemplo n.º 5
0
    def test_integrating_angular_components(self):
        """Test radial points that contain zero."""
        odg = OneDGrid(np.array([0.0, 1e-16, 1e-8, 1e-4, 1e-2]), np.ones(5),
                       (0, np.inf))
        atom_grid = AtomGrid(odg, degrees=[3])
        spherical = atom_grid.convert_cartesian_to_spherical()
        # Evaluate all spherical harmonics on the atomic grid points (r_i, theta_j, phi_j).
        spherical_harmonics = generate_real_spherical_harmonics(
            3,
            spherical[:, 1],
            spherical[:, 2]  # theta, phi points
        )
        # Convert to three-dimensional array (Degrees, Order, Points)
        spherical_array = np.zeros((3, 2 * 3 + 1, len(atom_grid.points)))
        spherical_array[0, 0, :] = spherical_harmonics[0, :]  # (l,m) = (0,0)
        spherical_array[1, 0, :] = spherical_harmonics[1, :]  # = (1, 0)
        spherical_array[1, 1, :] = spherical_harmonics[2, :]  # = (1, 1)
        spherical_array[1, 2, :] = spherical_harmonics[3, :]  # = (1, -1)
        spherical_array[2, 0, :] = spherical_harmonics[4, :]  # = (2, 0)
        spherical_array[2, 1, :] = spherical_harmonics[5, :]  # = (2, 2)
        spherical_array[2, 2, :] = spherical_harmonics[6, :]  # = (2, 1)
        spherical_array[2, 3, :] = spherical_harmonics[7, :]  # = (2, -2)
        spherical_array[2, 4, :] = spherical_harmonics[8, :]  # = (2, -1)

        integral = atom_grid.integrate_angular_coordinates(spherical_array)
        assert integral.shape == (3, 2 * 3 + 1, 5)
        # Assert that all spherical harmonics except when l=0,m=0 are all zero.
        assert_almost_equal(integral[0, 0, :], np.sqrt(4.0 * np.pi))
        assert_almost_equal(integral[0, 1:, :], 0.0)
        assert_almost_equal(integral[1:, :, :], 0.0)
Exemplo n.º 6
0
    def test_fitting_spherical_harmonics(self):
        r"""Test fitting the radial components of spherical harmonics is just a one, rest zeros."""
        max_degree = 10  # Maximum degree
        rad = OneDGrid(np.linspace(0.0, 1.0, num=10), np.ones(10), (0, np.inf))
        atom_grid = AtomGrid(rad, degrees=[max_degree])
        max_degree = atom_grid.l_max
        spherical = atom_grid.convert_cartesian_to_spherical()
        # Evaluate all spherical harmonics on the atomic grid points (r_i, theta_j, phi_j).
        spherical_harmonics = generate_real_spherical_harmonics(
            max_degree,
            spherical[:, 1],
            spherical[:, 2]  # theta, phi points
        )

        i = 0
        # Go through each spherical harmonic up to max_degree // 2 and check if projection
        # for its radial component is one and the rest are all zeros.
        for l_value in range(0, max_degree // 2):
            for m in ([0] + [x for x in range(1, l_value + 1)] +
                      [x for x in range(-l_value, 0)]):
                spherical_harm = spherical_harmonics[i, :]
                radial_components = atom_grid.radial_component_splines(
                    spherical_harm)
                assert len(radial_components) == (atom_grid.l_max // 2 +
                                                  1)**2.0

                radial_pts = np.arange(0.0, 1.0, 0.01)
                # Go Through each (l, m)
                for j, radial_comp in enumerate(radial_components):
                    # If the current index is j, then projection of spherical harmonic
                    # onto itself should be all ones, else they are all zero.
                    if i == j:
                        assert_almost_equal(radial_comp(radial_pts), 1.0)
                    else:
                        assert_almost_equal(radial_comp(radial_pts),
                                            0.0,
                                            decimal=8)
                i += 1