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)
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
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)
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)
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_cart_to_sph(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_cart_to_sph(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)
def test_generate_spherical(self): """Test generated real spherical harmonics values.""" atgrid = AngularGrid(degree=7) pts = atgrid.points wts = atgrid.weights r = np.linalg.norm(pts, axis=1) # polar phi = np.arccos(pts[:, 2] / r) # azimuthal theta = np.arctan2(pts[:, 1], pts[:, 0]) # generate spherical harmonics sph_h = AtomGrid._generate_real_sph_harm(3, theta, phi) # l_max = 3 assert sph_h.shape == (16, 26) for _ in range(100): n1, n2 = np.random.randint(0, 16, 2) re = sum(sph_h[n1] * sph_h[n2] * wts) if n1 != n2: print(n1, n2, re) assert_almost_equal(re, 0) else: print(n1, n2, re) assert_almost_equal(re, 1) for i in range(10): sph_h = AtomGrid._generate_real_sph_harm(i, theta, phi) assert sph_h.shape == ((i + 1)**2, 26)
def test_spherical_complete(self): """Test atomitc grid consistence for spherical integral.""" num_pts = len(LEBEDEV_DEGREES) pts = HortonLinear(num_pts) for _ in range(10): start = np.random.rand() * 1e-5 end = np.random.rand() * 10 + 10 tf = PowerRTransform(start, end) rad_grid = tf.transform_1d_grid(pts) atgrid = AtomGrid(rad_grid, degrees=list(LEBEDEV_DEGREES.keys())) values = np.random.rand(len(LEBEDEV_DEGREES)) pt_val = np.zeros(atgrid.size) for index, value in enumerate(values): pt_val[atgrid._indices[index]:atgrid._indices[index + 1]] = value rad_int_val = (value * rad_grid.weights[index] * 4 * np.pi * rad_grid.points[index]**2) atgrid_int_val = np.sum( pt_val[atgrid._indices[index]:atgrid._indices[index + 1]] * atgrid.weights[atgrid._indices[index]:atgrid. _indices[index + 1]]) assert_almost_equal(rad_int_val, atgrid_int_val) ref_int_at = atgrid.integrate(pt_val) ref_int_rad = rad_grid.integrate(4 * np.pi * rad_grid.points**2 * values) assert_almost_equal(ref_int_at, ref_int_rad)
def test_from_size(self): """Test horton style grid.""" nums = np.array([1, 1]) coors = np.array([[0, 0, -0.5], [0, 0, 0.5]]) becke = BeckeWeights(order=3) mol_grid = MolGrid.from_size(nums, coors, self.rgrid, 110, becke, rotate=False) atg1 = AtomGrid.from_pruned( self.rgrid, 0.5, sectors_r=np.array([]), sectors_degree=np.array([17]), center=coors[0], ) atg2 = AtomGrid.from_pruned( self.rgrid, 0.5, sectors_r=np.array([]), sectors_degree=np.array([17]), center=coors[1], ) ref_grid = MolGrid(nums, [atg1, atg2], becke, store=True) assert_allclose(ref_grid.points, mol_grid.points) assert_allclose(ref_grid.weights, mol_grid.weights)
def test_total_atomic_grid(self): """Normal initialization test.""" radial_pts = np.arange(0.1, 1.1, 0.1) radial_wts = np.ones(10) * 0.1 rgrid = OneDGrid(radial_pts, radial_wts) rad = 0.5 r_sectors = np.array([0.5, 1, 1.5]) degs = np.array([6, 14, 14, 6]) # generate a proper instance without failing. ag_ob = AtomGrid.from_pruned(rgrid, radius=rad, sectors_r=r_sectors, sectors_degree=degs) assert isinstance(ag_ob, AtomGrid) assert len(ag_ob.indices) == 11 assert ag_ob.l_max == 15 ag_ob = AtomGrid.from_pruned(rgrid, radius=rad, sectors_r=np.array([]), sectors_degree=np.array([6])) assert isinstance(ag_ob, AtomGrid) assert len(ag_ob.indices) == 11 ag_ob = AtomGrid(rgrid, sizes=[110]) assert ag_ob.l_max == 17 assert_array_equal(ag_ob._degs, np.ones(10) * 17) assert ag_ob.size == 110 * 10 # new init AtomGrid ag_ob2 = AtomGrid(rgrid, degrees=[17]) assert ag_ob2.l_max == 17 assert_array_equal(ag_ob2._degs, np.ones(10) * 17) assert ag_ob2.size == 110 * 10 assert isinstance(ag_ob.rgrid, OneDGrid) assert_allclose(ag_ob.rgrid.points, rgrid.points) assert_allclose(ag_ob.rgrid.weights, rgrid.weights)
def test_integrate_hydrogen_trimer_1s(self): """Test molecular integral in H3.""" coordinates = np.array( [[0.0, 0.0, -0.5], [0.0, 0.0, 0.5], [0.0, 0.5, 0.0]], float) atg1 = AtomGrid.from_pruned( self.rgrid, 0.5, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[0], ) atg2 = AtomGrid.from_pruned( self.rgrid, 0.5, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[1], ) atg3 = AtomGrid.from_pruned( self.rgrid, 0.5, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[2], ) becke = BeckeWeights(order=3) mg = MolGrid([atg1, atg2, atg3], becke, np.array([1, 1, 1])) dist0 = np.sqrt(((coordinates[0] - mg.points)**2).sum(axis=1)) dist1 = np.sqrt(((coordinates[1] - mg.points)**2).sum(axis=1)) dist2 = np.sqrt(((coordinates[2] - mg.points)**2).sum(axis=1)) fn = (np.exp(-2 * dist0) / np.pi + np.exp(-2 * dist1) / np.pi + np.exp(-2 * dist2) / np.pi) occupation = mg.integrate(fn) assert_almost_equal(occupation, 3.0, decimal=4)
def test_poisson_solve_mtr_cmpl(self): """Test solve poisson equation and interpolate the result.""" oned = GaussChebyshev(50) btf = BeckeRTransform(1e-7, 1.5) rad = btf.transform_1d_grid(oned) l_max = 7 atgrid = AtomGrid(rad, degrees=[l_max]) value_array = self.helper_func_gauss(atgrid.points) p_0 = atgrid.integrate(value_array) # test density sum up to np.pi**(3 / 2) assert_allclose(p_0, np.pi**1.5, atol=1e-4) sph_coor = atgrid.convert_cart_to_sph()[:, 1:3] spls_mt = Poisson._proj_sph_value( atgrid.rgrid, sph_coor, l_max // 2, value_array, atgrid.weights, atgrid.indices, ) ibtf = InverseRTransform(btf) linsp = np.linspace(-1, 0.99, 50) bound = p_0 * np.sqrt(4 * np.pi) pois_mtr = Poisson.solve_poisson(spls_mt, linsp, bound, tfm=ibtf) assert pois_mtr.shape == (7, 4) near_rg_pts = np.array([1e-2, 0.1, 0.2, 0.3, 0.5, 0.7, 1.0, 1.2]) near_tf_pts = ibtf.transform(near_rg_pts) ref_short_res = [ 6.28286, # 0.01 6.26219, # 0.1 6.20029, # 0.2 6.09956, # 0.3 5.79652, # 0.5 5.3916, # 0.7 4.69236, # 1.0 4.22403, # 1.2 ] for i, j in enumerate(near_tf_pts): assert_almost_equal( Poisson.interpolate_radial(pois_mtr, j, 0, True) / near_rg_pts[i], ref_short_res[i] * np.sqrt(4 * np.pi), decimal=3, ) matrix_result = Poisson.interpolate_radial(pois_mtr, j) assert_almost_equal( matrix_result[0, 0] / near_rg_pts[i], ref_short_res[i] * np.sqrt(4 * np.pi), decimal=3, ) # test interpolate with sph result = Poisson.interpolate(pois_mtr, j, np.random.rand(5), np.random.rand(5)) assert_allclose(result / near_rg_pts[i] - ref_short_res[i], np.zeros(5), atol=1e-3)
def test_atomic_grid(self): """Test atomic grid center transilation.""" 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]) # origin center # randome center pts, wts, ind = AtomGrid._generate_atomic_grid(rad_grid, degs) ref_pts, ref_wts, ref_ind = AtomGrid._generate_atomic_grid(rad_grid, degs) # diff grid points diff by center and same weights assert_allclose(pts, ref_pts) assert_allclose(wts, ref_wts)
def test_interpolation_of_laplacian_with_spherical_harmonic(self): r"""Test the interpolation of Laplacian of spherical harmonic is eigenvector.""" odg = OneDGrid(np.linspace(0.0, 10, num=2000), np.ones(2000), (0, np.inf)) rad = IdentityRTransform().transform_1d_grid(odg) degree = 6 * 2 + 2 atgrid = AtomGrid.from_pruned(rad, 1, sectors_r=[], sectors_degree=[degree]) def func(sph_points): # Spherical harmonic of order 6 and magnetic 0 r, phi, theta = sph_points.T return (np.sqrt(2.0) * 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)) # Get spherical points from atomic grid spherical_pts = atgrid.convert_cartesian_to_spherical(atgrid.points) func_values = func(spherical_pts) laplacian = atgrid.interpolate_laplacian(func_values) # Test on the same points used for interpolation and random points. for grid in [atgrid.points, np.random.uniform(-0.75, 0.75, (250, 3))]: actual = laplacian(grid) spherical_pts = atgrid.convert_cartesian_to_spherical(grid) # Eigenvector spherical harmonic times l(l + 1) / r^2 with np.errstate(divide="ignore", invalid="ignore"): desired = (-func(spherical_pts) * 6 * (6 + 1) / spherical_pts[:, 0]**2.0) desired[spherical_pts[:, 0]**2.0 < 1e-10] = 0.0 assert_almost_equal(actual, desired, decimal=3)
def test_spline_with_sph_harms(self): """Test spline projection the same as spherical harmonics.""" odg = OneDGrid(np.arange(10) + 1, np.ones(10), (0, np.inf)) rad = IdentityRTransform().transform_1d_grid(odg) atgrid = AtomGrid.from_pruned(rad, 1, sectors_r=[], sectors_degree=[7]) sph_coor = atgrid.convert_cart_to_sph() values = self.helper_func_power(atgrid.points) l_max = atgrid.l_max // 2 r_sph = generate_real_sph_harms(l_max, sph_coor[:, 1], sph_coor[:, 2]) result = spline_with_sph_harms(r_sph, values, atgrid.weights, atgrid.indices, rad) # generate ref for shell in range(1, 11): sh_grid = atgrid.get_shell_grid(shell - 1, r_sq=False) # Convert to spherical harmonics r = np.linalg.norm(sh_grid._points, axis=1) theta = np.arctan2(sh_grid._points[:, 1], sh_grid._points[:, 0]) phi = np.arccos(sh_grid._points[:, 2] / r) # General all spherical harmonics up to l_max r_sph = generate_real_sph_harms(l_max, theta, phi) # Project the function 2x^2 + 3y^2 + 4z^2 r_sph_proj = np.sum( r_sph * self.helper_func_power(sh_grid.points) * sh_grid.weights, axis=-1, ) # Check the actual projection against the cubic spline interpolation. assert_allclose(r_sph_proj, result(shell), atol=1e-10)
def test_interpolation_of_laplacian_of_exponential(self): r"""Test the interpolation of Laplacian of exponential.""" odg = OneDGrid(np.linspace(0.01, 1, num=1000), np.ones(1000), (0, np.inf)) degree = 10 atgrid = AtomGrid.from_pruned(odg, 1, sectors_r=[], sectors_degree=[degree]) def func(cart_pts): radius = np.linalg.norm(cart_pts, axis=1) return np.exp(-radius) func_values = func(atgrid.points) laplacian = atgrid.interpolate_laplacian(func_values) # Test on the same points used for interpolation and random points. for grid in [atgrid.points, np.random.uniform(-0.5, 0.5, (250, 3))]: actual = laplacian(grid) spherical_pts = atgrid.convert_cartesian_to_spherical(grid) # Laplacian of exponential is e^-x (x - 2) / x desired = (np.exp(-spherical_pts[:, 0]) * (spherical_pts[:, 0] - 2.0) / spherical_pts[:, 0]) assert_almost_equal(actual, desired, decimal=3)
def test_cubicspline_and_deriv(self): """Test spline for derivation.""" odg = OneDGrid(np.arange(10) + 1, np.ones(10), (0, np.inf)) rad = IdentityRTransform().transform_1d_grid(odg) for _ in range(10): degree = np.random.randint(5, 20) atgrid = AtomGrid.from_pruned(rad, 1, sectors_r=[], sectors_degree=[degree]) values = self.helper_func_power(atgrid.points) # spls = atgrid.fit_values(values) for i in range(10): interp = atgrid.interpolate( atgrid.points[atgrid.indices[i]:atgrid.indices[i + 1]], values, deriv=1, ) # same result from points and interpolation ref_deriv = self.helper_func_power_deriv( atgrid.points[atgrid.indices[i]:atgrid.indices[i + 1]]) assert_allclose(interp, ref_deriv) # test random x, y, z with fd for _ in range(10): xyz = np.random.rand(10, 3) * np.random.uniform(1, 6) ref_value = self.helper_func_power_deriv(xyz) interp = atgrid.interpolate(xyz, values, deriv=1) assert_allclose(interp, ref_value)
def test_cubicspline_and_interp(self): """Test cubicspline interpolation values.""" odg = OneDGrid(np.arange(10) + 1, np.ones(10), (0, np.inf)) rad_grid = IdentityRTransform().transform_1d_grid(odg) for _ in range(10): degree = np.random.randint(5, 20) atgrid = AtomGrid.from_pruned(rad_grid, 1, sectors_r=[], sectors_degree=[degree]) values = self.helper_func_power(atgrid.points) # spls = atgrid.fit_values(values) for i in range(10): interp = atgrid.interpolate( atgrid.points[atgrid.indices[i]:atgrid.indices[i + 1]], values) # same result from points and interpolation assert_allclose( interp, values[atgrid.indices[i]:atgrid.indices[i + 1]]) # test random x, y, z for _ in range(10): xyz = np.random.rand(10, 3) * np.random.uniform(1, 6) # xyz /= np.linalg.norm(xyz, axis=-1)[:, None] # rad = np.random.normal() * np.random.randint(1, 11) # xyz *= rad ref_value = self.helper_func_power(xyz) interp = atgrid.interpolate(xyz, values) assert_allclose(interp, ref_value)
def test_molgrid_attrs(self): """Test MolGrid attributes.""" # numbers = np.array([6, 8], int) coordinates = np.array([[0.0, 0.2, -0.5], [0.1, 0.0, 0.5]], float) atg1 = AtomGrid.from_pruned( self.rgrid, 1.228, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[0], ) atg2 = AtomGrid.from_pruned( self.rgrid, 0.945, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[1], ) becke = BeckeWeights(order=3) mg = MolGrid([atg1, atg2], becke, np.array([6, 8]), store=True) assert mg.size == 2 * 110 * 100 assert mg.points.shape == (mg.size, 3) assert mg.weights.shape == (mg.size, ) assert mg.aim_weights.shape == (mg.size, ) assert mg.get_atomic_grid(0) is atg1 assert mg.get_atomic_grid(1) is atg2 simple_ag1 = mg.get_atomic_grid(0) simple_ag2 = mg.get_atomic_grid(1) assert_allclose(simple_ag1.points, atg1.points) assert_allclose(simple_ag1.weights, atg1.weights) assert_allclose(simple_ag2.weights, atg2.weights) # test molgrid is not stored mg2 = MolGrid([atg1, atg2], becke, np.array([6, 8]), store=False) assert mg2._atomic_grids is None simple2_ag1 = mg2.get_atomic_grid(0) simple2_ag2 = mg2.get_atomic_grid(1) assert isinstance(simple2_ag1, LocalGrid) assert isinstance(simple2_ag2, LocalGrid) assert_allclose(simple2_ag1.points, atg1.points) assert_allclose(simple2_ag1.weights, atg1.weights) assert_allclose(simple2_ag2.weights, atg2.weights)
def test_molgrid_attrs_subgrid(self): """Test sub atomic grid attributes.""" # numbers = np.array([6, 8], int) coordinates = np.array([[0.0, 0.2, -0.5], [0.1, 0.0, 0.5]], float) atg1 = AtomGrid.from_pruned( self.rgrid, 1.228, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[0], ) atg2 = AtomGrid.from_pruned( self.rgrid, 0.945, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[1], ) becke = BeckeWeights(order=3) mg = MolGrid([atg1, atg2], becke, np.array([6, 8]), store=True) # mg = BeckeMolGrid(coordinates, numbers, None, (rgrid, 110), mode='keep') assert mg.size == 2 * 110 * 100 assert mg.points.shape == (mg.size, 3) assert mg.weights.shape == (mg.size, ) assert mg.aim_weights.shape == (mg.size, ) assert len(mg._indices) == 2 + 1 # assert mg.k == 3 # assert mg.random_rotate for i in range(2): atgrid = mg[i] assert isinstance(atgrid, AtomGrid) assert atgrid.size == 100 * 110 assert atgrid.points.shape == (100 * 110, 3) assert atgrid.weights.shape == (100 * 110, ) assert (atgrid.center == coordinates[i]).all() mg = MolGrid([atg1, atg2], becke, np.array([6, 8])) for i in range(2): atgrid = mg[i] assert isinstance(atgrid, LocalGrid) assert_allclose(atgrid.center, mg._coors[i])
def test_find_l_for_rad_list(self): """Test private method find_l_for_rad_list.""" radial_pts = np.arange(0.1, 1.1, 0.1) radial_wts = np.ones(10) * 0.1 rgrid = OneDGrid(radial_pts, radial_wts) rad = 1 r_sectors = np.array([0.2, 0.4, 0.8]) degs = np.array([3, 5, 7, 3]) atomic_grid_degree = AtomGrid._find_l_for_rad_list( rgrid.points, rad * r_sectors, degs) assert_equal(atomic_grid_degree, [3, 3, 5, 5, 7, 7, 7, 7, 3, 3])
def test_cubicspline_and_interp_mol(self): """Test cubicspline interpolation values.""" odg = OneDGrid(np.arange(10) + 1, np.ones(10), (0, np.inf)) rad = IdentityRTransform().transform_1d_grid(odg) atgrid = AtomGrid.from_pruned(rad, 1, sectors_r=[], sectors_degree=[7]) values = self.helper_func_power(atgrid.points) result = spline_with_atomic_grid(atgrid, values) sph_coor = atgrid.convert_cart_to_sph() semi_sph_c = sph_coor[atgrid.indices[5] : atgrid.indices[6]] interp = interpolate(result, rad.points[5], semi_sph_c[:, 1], semi_sph_c[:, 2]) # same result from points and interpolation assert_allclose(interp, values[atgrid.indices[5] : atgrid.indices[6]])
def test_from_pruned_with_degs_and_size(self): """Test different initilize method.""" radial_pts = np.arange(0.1, 1.1, 0.1) radial_wts = np.ones(10) * 0.1 rgrid = OneDGrid(radial_pts, radial_wts) rad = 0.5 r_sectors = np.array([0.5, 1, 1.5]) degs = np.array([3, 5, 7, 5]) size = np.array([6, 14, 26, 14]) # construct atomic grid with degs atgrid1 = AtomGrid.from_pruned( rgrid, radius=rad, sectors_r=r_sectors, sectors_degree=degs ) # construct atomic grid with size atgrid2 = AtomGrid.from_pruned( rgrid, radius=rad, sectors_r=r_sectors, sectors_size=size ) # test two grids are the same assert_equal(atgrid1.size, atgrid2.size) assert_allclose(atgrid1.points, atgrid2.points) assert_allclose(atgrid1.weights, atgrid2.weights)
def test_poisson_proj(self): """Test the project function.""" oned = GaussChebyshev(30) btf = BeckeRTransform(0.0001, 1.5) rad = btf.transform_1d_grid(oned) l_max = 7 atgrid = AtomGrid(rad, degrees=[l_max]) value_array = self.helper_func_gauss(atgrid.points) spl_res = spline_with_atomic_grid(atgrid, value_array) # test for random, r, theta, phi for _ in range(20): r = np.random.rand(1)[0] * 2 theta = np.random.rand(10) * 3.14 phi = np.random.rand(10) * 3.14 result = interpolate(spl_res, r, theta, phi) x = r * np.sin(phi) * np.cos(theta) y = r * np.sin(phi) * np.sin(theta) z = r * np.cos(phi) result_ref = self.helper_func_gauss(np.array([x, y, z]).T) # assert similar value less than 1e-4 discrepancy assert_allclose(result, result_ref, atol=1e-4) sph_coor = atgrid.convert_cart_to_sph()[:, 1:3] spls_mt = Poisson._proj_sph_value( atgrid.rgrid, sph_coor, l_max // 2, value_array, atgrid.weights, atgrid.indices, ) # test each point is the same for _ in range(20): r = np.random.rand(1)[0] * 2 # random spherical point int_res = np.zeros((l_max, l_max // 2 + 1), dtype=float) for j in range(l_max // 2 + 1): for i in range(-j, j + 1): int_res[i, j] += spls_mt[i, j](r) assert_allclose(spl_res(r), int_res)
def test_cubicspline_and_interp_mol(self): """Test cubicspline interpolation values.""" odg = OneDGrid(np.arange(10) + 1, np.ones(10), (0, np.inf)) rad = IdentityRTransform().transform_1d_grid(odg) atgrid = AtomGrid.from_pruned(rad, 1, sectors_r=[], sectors_degree=[7]) values = self.helper_func_power(atgrid.points) # spls = atgrid.fit_values(values) for i in range(10): interp = atgrid.interpolate( atgrid.points[atgrid.indices[i]:atgrid.indices[i + 1]], values) # same result from points and interpolation assert_allclose(interp, values[atgrid.indices[i]:atgrid.indices[i + 1]])
def test_raises_errors(self): """Test proper error raises.""" oned = GaussChebyshev(50) btf = BeckeRTransform(1e-7, 1.5) rad = btf.transform_1d_grid(oned) l_max = 7 atgrid = AtomGrid(rad, degrees=[l_max]) value_array = self.helper_func_gauss(atgrid.points) p_0 = atgrid.integrate(value_array) # test density sum up to np.pi**(3 / 2) assert_allclose(p_0, np.pi**1.5, atol=1e-4) sph_coor = atgrid.convert_cart_to_sph() with self.assertRaises(ValueError): Poisson._proj_sph_value( atgrid.rgrid, sph_coor, l_max // 2, value_array, atgrid.weights, atgrid.indices, )
def test_derivative_of_interpolate_given_splines(self): """Test the spline interpolating derivative of function in radial coordinate.""" odg = OneDGrid(np.arange(10) + 1, np.ones(10), (0, np.inf)) rad = IdentityRTransform().transform_1d_grid(odg) atgrid = AtomGrid.from_pruned(rad, 1, sectors_r=[], sectors_degree=[7]) sph_coor = atgrid.convert_cart_to_sph() values = self.helper_func_power(atgrid.points) l_max = atgrid.l_max // 2 r_sph = generate_real_sph_harms(l_max, sph_coor[:, 1], sph_coor[:, 2]) result = spline_with_sph_harms(r_sph, values, atgrid.weights, atgrid.indices, rad) semi_sph_c = sph_coor[atgrid.indices[5]:atgrid.indices[6]] interp = interpolate_given_splines(result, 6, semi_sph_c[:, 1], semi_sph_c[:, 2], deriv=1) # same result from points and interpolation ref_deriv = self.helper_func_power_deriv( atgrid.points[atgrid.indices[5]:atgrid.indices[6]]) assert_allclose(interp, ref_deriv) # test random x, y, z with fd xyz = np.random.rand(1, 3) xyz /= np.linalg.norm(xyz, axis=-1)[:, None] rad = np.random.normal() * np.random.randint(1, 11) xyz *= rad ref_value = self.helper_func_power_deriv(xyz) r = np.linalg.norm(xyz, axis=-1) theta = np.arctan2(xyz[:, 1], xyz[:, 0]) phi = np.arccos(xyz[:, 2] / r) interp = interpolate_given_splines(result, np.abs(rad), theta, phi, deriv=1) assert_allclose(interp, ref_value) with self.assertRaises(ValueError): interpolate_given_splines(result, 6, semi_sph_c[:, 1], semi_sph_c[:, 2], deriv=4) with self.assertRaises(ValueError): interpolate_given_splines(result, 6, semi_sph_c[:, 1], semi_sph_c[:, 2], deriv=-1)
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
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, degrees=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 = AngularGrid(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 = AngularGrid(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 test_integrate_hirshfeld_weights_pair_1s(self): """Test molecular integral in H2.""" coordinates = np.array([[0.0, 0.0, -0.5], [0.0, 0.0, 0.5]]) atg1 = AtomGrid.from_pruned( self.rgrid, 0.5, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[0], ) atg2 = AtomGrid.from_pruned( self.rgrid, 0.5, r_sectors=np.array([]), degs=np.array([17]), center=coordinates[1], ) mg = MolGrid([atg1, atg2], HirshfeldWeights(), np.array([1, 1])) dist0 = np.sqrt(((coordinates[0] - mg.points)**2).sum(axis=1)) dist1 = np.sqrt(((coordinates[1] - mg.points)**2).sum(axis=1)) fn = np.exp(-2 * dist0) / np.pi + 1.5 * np.exp(-2 * dist1) / np.pi occupation = mg.integrate(fn) assert_almost_equal(occupation, 2.5, decimal=5)
def test_horton_molgrid(self): """Test horton style grid.""" nums = np.array([1, 1]) coors = np.array([[0, 0, -0.5], [0, 0, 0.5]]) becke = BeckeWeights(order=3) mol_grid = MolGrid.horton_molgrid(coors, nums, self.rgrid, 110, becke) atg1 = AtomGrid.from_pruned( self.rgrid, 0.5, r_sectors=np.array([]), degs=np.array([17]), center=coors[0], ) atg2 = AtomGrid.from_pruned( self.rgrid, 0.5, r_sectors=np.array([]), degs=np.array([17]), center=coors[1], ) ref_grid = MolGrid([atg1, atg2], becke, nums, store=True) assert_allclose(ref_grid.points, mol_grid.points) assert_allclose(ref_grid.weights, mol_grid.weights)