def test_convert_cart_to_sph(self): """Test convert_cart_sph accuracy.""" for _ in range(10): pts = np.random.rand(10, 3) center = np.random.rand(3) # given center sph_coor = convert_cart_to_sph(pts, center) assert_equal(sph_coor.shape, pts.shape) # Check Z z = sph_coor[:, 0] * np.cos(sph_coor[:, 2]) assert_allclose(z, pts[:, 2] - center[2]) # Check x xy = sph_coor[:, 0] * np.sin(sph_coor[:, 2]) x = xy * np.cos(sph_coor[:, 1]) assert_allclose(x, pts[:, 0] - center[0]) # Check y y = xy * np.sin(sph_coor[:, 1]) assert_allclose(y, pts[:, 1] - center[1]) # no center sph_coor = convert_cart_to_sph(pts) assert_equal(sph_coor.shape, pts.shape) # Check Z z = sph_coor[:, 0] * np.cos(sph_coor[:, 2]) assert_allclose(z, pts[:, 2]) # Check x xy = sph_coor[:, 0] * np.sin(sph_coor[:, 2]) x = xy * np.cos(sph_coor[:, 1]) assert_allclose(x, pts[:, 0]) # Check y y = xy * np.sin(sph_coor[:, 1]) assert_allclose(y, pts[:, 1])
def convert_cartesian_to_spherical(self, points: np.ndarray = None, center: np.ndarray = None): r"""Convert a set of points from Cartesian to spherical coordinates. The conversion is defined as .. math:: \begin{align} r &= \sqrt{x^2 + y^2 + z^2}\\ \theta &= arc\tan (\frac{y}{x})\\ \phi &= arc\cos(\frac{z}{r}) \end{align} with the canonical choice :math:`r=0`, then :math:`\theta,\phi = 0`. If the `points` attribute is not specified, then atomic grid points are used and the canonical choice when :math:`r=0`, is the points :math:`(r=0, \theta_j, \phi_j)` where :math:`(\theta_j, \phi_j)` come from the Angular/Lebedev grid with the degree at :math:`r=0`. Parameters ---------- points : ndarray(n, 3), optional Points in three-dimensions. Atomic grid points will be used if `points` is not given center : ndarray(3,), optional Center of the atomic grid points. If `center` is not provided, then the atomic center of this class is used. Returns ------- ndarray(N, 3) Spherical coordinates of atoms respect to the center (radius :math:`r`, azimuthal :math:`\theta`, polar :math:`\phi`). """ is_atomic = False if points is None: points = self.points is_atomic = True if points.ndim == 1: points = points.reshape(-1, 3) center = self.center if center is None else np.asarray(center) spherical_points = convert_cart_to_sph(points, center) # If atomic grid points are being converted, then choose canonical angles (when r=0) # to be from the degree specified of that point. The reasoning is to insure that # the integration of spherical harmonic when l=l, m=0, is zero even when r=0. if is_atomic: r_index = np.where(self.rgrid.points == 0.0)[0] for i in r_index: # build angular grid for the degree at r=0 agrid = AngularGrid(degree=self._degs[i]) start_index = self._indices[i] final_index = self._indices[i + 1] spherical_points[start_index:final_index, 1:] = convert_cart_to_sph(agrid.points)[:, 1:] return spherical_points
def test_convert_cart_to_sph_origin(self): """Test convert_cart_sph at origin.""" # point at origin pts = np.array([[0.0, 0.0, 0.0]]) sph_coor = convert_cart_to_sph(pts, center=None) assert_allclose(sph_coor, 0.0) # point very close to origin pts = np.array([[1.0e-15, 1.0e-15, 1.0e-15]]) sph_coor = convert_cart_to_sph(pts, center=None) assert sph_coor[0, 0] < 1.0e-12 assert np.all(sph_coor[0, 1:] < 1.0) # point very very close to origin pts = np.array([[1.0e-100, 1.0e-100, 1.0e-100]]) sph_coor = convert_cart_to_sph(pts, center=None) assert sph_coor[0, 0] < 1.0e-12 assert np.all(sph_coor[0, 1:] < 1.0)
def test_generate_real_spherical_is_accurate(self): r"""Test generated real spherical harmonic up to degree 3 is accurate.""" numb_pts = 100 pts = np.random.uniform(-1.0, 1.0, size=(numb_pts, 3)) sph_pts = convert_cart_to_sph(pts) r, theta, phi = sph_pts[:, 0], sph_pts[:, 1], sph_pts[:, 2] sph_h = generate_real_spherical_harmonics(3, theta, phi) # l_max = 3 # Test l=0, m=0 assert_allclose(sph_h[0, :], np.ones(len(theta)) / np.sqrt(4.0 * np.pi)) # Test l=1, m=0, obtained from wikipedia assert_allclose(sph_h[1, :], np.sqrt(3.0 / (4.0 * np.pi)) * pts[:, 2] / r) # Test l=1, m=1, m=0 assert_allclose(sph_h[2, :], np.sqrt(3.0 / (4.0 * np.pi)) * pts[:, 0] / r) assert_allclose(sph_h[3, :], np.sqrt(3.0 / (4.0 * np.pi)) * pts[:, 1] / r)
def test_raise_errors(self): """Test raise proper errors.""" with self.assertRaises(ValueError): get_cov_radii(3, type="random") with self.assertRaises(ValueError): get_cov_radii(0) with self.assertRaises(ValueError): get_cov_radii([3, 5, 0]) with self.assertRaises(ValueError): pts = np.random.rand(10) convert_cart_to_sph(pts, np.zeros(3)) with self.assertRaises(ValueError): pts = np.random.rand(10, 3, 1) convert_cart_to_sph(pts, np.zeros(3)) with self.assertRaises(ValueError): pts = np.random.rand(10, 2) convert_cart_to_sph(pts, np.zeros(3)) with self.assertRaises(ValueError): pts = np.random.rand(10, 3) convert_cart_to_sph(pts, np.zeros(2))
def convert_cart_to_sph(self, points=None, center=None): """Convert a set of points from cartesian to spherical coordinates. Parameters ---------- points : np.ndarray(n, 3), optional 3 dimentional numpy array for points atomic grid points will be used if `points` is not given center : np.ndarray(3,), optional center of the spherical coordinates atomic center will be used if `center` is not given Returns ------- np.ndarray(N, 3) Spherical coordinates of atoms respect to the center [radius, azumuthal, polar] """ if points is None: points = self.points if points.ndim == 1: points = points.reshape(-1, 3) center = self.center if center is None else np.asarray(center) return convert_cart_to_sph(points, center)