def _generate_atomic_grid(rgrid, degs, rotate=False): """Generate atomic grid for each radial point with angular degree L. Parameters ---------- rgrid : Grid, radial grid of given atomic grid. degs : np.ndarray(N,), an array of magic number for each radial point. rotate : boolean or int, whether a rotation will be applied to grid Returns ------- tuple(np.ndarray(M,), np.ndarray(M,), np.ndarray(N,)), grid points, grid weights, and indices for each shell. """ if len(degs) != rgrid.size: raise ValueError( "The shape of radial grid does not match given degs.") all_points, all_weights = [], [] # Preload spherical information in case of repeated IO unique_degs = np.unique(degs) sphere_grids = { i: generate_lebedev_grid(degree=i) for i in unique_degs } shell_pt_indices = np.zeros(len(degs) + 1, dtype=int) # set index to int for i, deg_i in enumerate(degs): # TODO: proper tests sphere_grid = sphere_grids[deg_i] if rotate is False: pass # if rotate is True, rotate each shell elif rotate is True: rot_mt = R.random().as_matrix() new_points = sphere_grid.points @ rot_mt sphere_grid = AngularGrid(new_points, sphere_grid.weights) # if rotate is a seed else: assert isinstance(rotate, int) # check seed proper value rot_mt = R.random(random_state=rotate + i).as_matrix() new_points = sphere_grid.points @ rot_mt sphere_grid = AngularGrid(new_points, sphere_grid.weights) # construct atomic grid with each radial point and each spherical shell # compute points points = sphere_grid.points * rgrid[i].points # compute weights weights = sphere_grid.weights * rgrid[i].weights * rgrid[ i].points**2 # locate separators shell_pt_indices[i + 1] = shell_pt_indices[i] + len(points) all_points.append(points) all_weights.append(weights) indices = shell_pt_indices points = np.vstack(all_points) weights = np.hstack(all_weights) return points, weights, indices
def test_get_shell_grid(self): """Test angular grid get from get_shell_grid function.""" 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) degs = [3, 5, 7] atgrid = AtomGrid(rad_grid, degs=degs) assert atgrid.n_shells == 3 # grep shell with r^2 for i in range(atgrid.n_shells): sh_grid = atgrid.get_shell_grid(i) assert isinstance(sh_grid, AngularGrid) ref_grid = generate_lebedev_grid(degree=degs[i]) assert np.allclose(sh_grid.points, ref_grid.points * rad_pts[i]) assert np.allclose(sh_grid.weights, ref_grid.weights * rad_wts[i] * rad_pts[i]**2) # grep shell without r^2 for i in range(atgrid.n_shells): sh_grid = atgrid.get_shell_grid(i, r_sq=False) assert isinstance(sh_grid, AngularGrid) ref_grid = generate_lebedev_grid(degree=degs[i]) assert np.allclose(sh_grid.points, ref_grid.points * rad_pts[i]) assert np.allclose(sh_grid.weights, ref_grid.weights * rad_wts[i])
def _preload_unit_sphere_grid(degs): """Preload spherical information incase repeated IO. Parameters ---------- degs : np.ndarray(N,), an array of preferred magic number degrees. Returns ------- dict{degree: AngularGrid} """ # if non-magic number will bring redundancy. But it only link by ref, # so the efficiency would be fine. unique_degs = np.unique(degs) return {i: generate_lebedev_grid(degree=i) for i in unique_degs}
def test_lebedev_laikov_sphere(self): """Levedev grid tests from old grid.""" previous_npoint = 0 for i in range(1, 132): npoint = _select_grid_type(degree=i)[1] if npoint > previous_npoint: grid = generate_lebedev_grid(size=npoint) assert isinstance(grid, AngularGrid) assert_allclose(grid.weights.sum(), 1.0 * 4 * np.pi) assert_allclose(grid.points[:, 0].sum(), 0, atol=1e-10) assert_allclose(grid.points[:, 1].sum(), 0, atol=1e-10) assert_allclose(grid.points[:, 2].sum(), 0, atol=1e-10) assert_allclose(np.dot(grid.points[:, 0], grid.weights), 0, atol=1e-10) assert_allclose(np.dot(grid.points[:, 1], grid.weights), 0, atol=1e-10) assert_allclose(np.dot(grid.points[:, 2], grid.weights), 0, atol=1e-10) previous_npoint = npoint
def test_generate_atomic_grid(self): """Test for generating atomic grid.""" # setup testing class 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) degs = np.array([3, 5, 7]) pts, wts, ind = AtomGrid._generate_atomic_grid(rad_grid, degs) assert len(pts) == 46 assert_equal(ind, [0, 6, 20, 46]) # set tests for slicing grid from atomic grid for i in range(3): # set each layer of points ref_grid = generate_lebedev_grid(degree=degs[i]) # check for each point assert_allclose(pts[ind[i]:ind[i + 1]], ref_grid.points * rad_pts[i]) # check for each weight assert_allclose( wts[ind[i]:ind[i + 1]], ref_grid.weights * rad_wts[i] * rad_pts[i]**2, )
def setUp(self): """Generate atomic grid for constant test call.""" self.ang_grid = generate_lebedev_grid(degree=7)
def test_errors_and_warnings(self): """Tests for errors and warning.""" # low level function tests with self.assertRaises(ValueError): _select_grid_type() with self.assertRaises(ValueError): _select_grid_type(degree=-1) with self.assertRaises(ValueError): _select_grid_type(degree=132) with self.assertRaises(ValueError): _select_grid_type(size=-1) with self.assertRaises(ValueError): _select_grid_type(size=6000) with self.assertWarns(RuntimeWarning): _select_grid_type(degree=5, size=10) # high level function tests with self.assertRaises(ValueError): generate_lebedev_grid() with self.assertRaises(ValueError): generate_lebedev_grid(size=6000) with self.assertRaises(ValueError): generate_lebedev_grid(size=-1) with self.assertRaises(ValueError): generate_lebedev_grid(degree=132) with self.assertRaises(ValueError): generate_lebedev_grid(degree=-2) with self.assertWarns(RuntimeWarning): generate_lebedev_grid(degree=5, size=10)