def test_becke_transform_f0_ode(self): """Test same result for 3rd order ode with becke tf and fx term.""" btf = BeckeRTransform(0.1, 10) x = np.linspace(-0.9, 0.9, 20) btf = BeckeRTransform(0.1, 5) ibtf = InverseRTransform(btf) r = btf.transform(x) y = np.random.rand(2, x.size) coeff = [-1, -1, 2] def fx(x): return -1 / x**2 def func(x, y): dy_dx = ODE._rearrange_trans_ode(x, y, coeff, ibtf, fx) return np.vstack((*y[1:], dy_dx)) def bc(ya, yb): return np.array([ya[0], yb[0]]) res = solve_bvp(func, bc, x, y) def func_ref(x, y): dy_dx = ODE._rearrange_ode(x, y, coeff, fx(x)) return np.vstack((*y[1:], dy_dx)) res_ref = solve_bvp(func_ref, bc, r, y) assert_allclose(res.sol(x)[0], res_ref.sol(r)[0], atol=1e-4)
def test_becke_parameter_calc(self): """Test parameter function.""" R = BeckeRTransform.find_parameter(self.array, 0.1, 1.2) # R = 1.1 assert np.isclose(R, 1.1) btf = BeckeRTransform(0.1, R) tf_array = btf.transform(self.array) assert tf_array[9] == 1.2 # for even number of grid R = BeckeRTransform.find_parameter(self.array_2, 0.2, 1.3) btf_2 = BeckeRTransform(0.2, R) tf_elemt = btf_2.transform( np.array([(self.array_2[4] + self.array_2[5]) / 2])) assert_allclose(tf_elemt, 1.3)
def test_becke_transform_3nd_order_ode(self): """Test same result for 3rd order ode with becke tf.""" btf = BeckeRTransform(0.1, 10) ibtf = InverseRTransform(btf) coeff = np.array([0, 2, 3, 3]) # transform # r = np.linspace(1, 2, 10) # r # x = ibtf.transform(r) # transformed x x = np.linspace(-0.9, 0.9, 20) r = ibtf.inverse(x) y = np.random.rand(3, r.size) def fx(x): return 1 / x**4 def func(x, y): dy_dx = ODE._rearrange_trans_ode(x, y, coeff, ibtf, fx) return np.vstack((*y[1:], dy_dx)) def bc(ya, yb): return np.array([ya[0], yb[0], ya[1]]) res = solve_bvp(func, bc, x, y) # print(res.sol(x)[0]) def func_ref(x, y): dy_dx = ODE._rearrange_ode(x, y, coeff, fx(x)) return np.vstack((*y[1:], dy_dx)) res_ref = solve_bvp(func_ref, bc, r, y) # print(res_ref.sol(r)[0]) assert_allclose(res.sol(x)[0], res_ref.sol(r)[0], atol=1e-4)
def test_error_raises(self): """Test proper error raises.""" x = np.linspace(-0.999, 0.999, 20) # r = btf.transform(x) def fx(x): return 1 / x**2 coeffs = [-1, -2, 1] bd_cond = [(0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0)] with self.assertRaises(NotImplementedError): ODE.solve_ode(x, fx, coeffs, bd_cond[3:]) with self.assertRaises(NotImplementedError): ODE.solve_ode(x, fx, coeffs, bd_cond) with self.assertRaises(NotImplementedError): test_coeff = [1, 2, 3, 4, 5] ODE.solve_ode(x, fx, test_coeff, bd_cond) with self.assertRaises(ValueError): test_coeff = [1, 2, 3, 3] tf = BeckeRTransform(0.1, 1) def fx(x): return x ODE.solve_ode(x, fx, test_coeff, bd_cond[:3], tf)
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_becke_transform(self): """Test becke transformation.""" btf = BeckeRTransform(0.1, 1.1) tf_array = btf.transform(self.array) single_v = btf.transform(self.num) single_v2 = btf.transform(self.num_2) new_array = btf.inverse(tf_array) assert_allclose(new_array, self.array) assert_allclose(tf_array[0], single_v) assert_allclose(tf_array[-1], single_v2) # test tf and inverse self._transform_and_inverse(-1, 1, btf)
def test_errors_assert(self): """Test errors raise.""" # parameter error with self.assertRaises(ValueError): BeckeRTransform.find_parameter(np.arange(5), 0.5, 0.1) # transform non array type with self.assertRaises(TypeError): btf = BeckeRTransform(0.1, 1.1) btf.transform("dafasdf") # inverse init error with self.assertRaises(TypeError): InverseRTransform(0.5) # type error for transform_1d_grid with self.assertRaises(TypeError): btf = BeckeRTransform(0.1, 1.1) btf.transform_1d_grid(np.arange(3)) with self.assertRaises(ZeroDivisionError): btf = BeckeRTransform(0.1, 0) itf = InverseRTransform(btf) itf._d1(0.5) with self.assertRaises(ZeroDivisionError): btf = BeckeRTransform(0.1, 0) itf = InverseRTransform(btf) itf._d1(np.array([0.1, 0.2, 0.3]))
def test_solver_ode_bvp_with_tf(self): """Test result for high level api solve_ode with fx term.""" x = np.linspace(-0.999, 0.999, 20) btf = BeckeRTransform(0.1, 5) r = btf.transform(x) ibtf = InverseRTransform(btf) def fx(x): return 1 / x**2 coeffs = [-1, 1, 1] bd_cond = [(0, 0, 0), (1, 0, 0)] # calculate diff equation wt/w tf. res = ODE.solve_ode(x, fx, coeffs, bd_cond, ibtf) res_ref = ODE.solve_ode(r, fx, coeffs, bd_cond) assert_allclose(res(x)[0], res_ref(r)[0], atol=1e-4)
def test_solver_ode_coeff_a_f_x_with_tf(self): """Test ode with a(x) and f(x) involved.""" x = np.linspace(-0.999, 0.999, 20) btf = BeckeRTransform(0.1, 5) r = btf.transform(x) ibtf = InverseRTransform(btf) def fx(x): return 0 * x coeffs = [lambda x: x**2, lambda x: 1 / x**2, 0.5] bd_cond = [(0, 0, 0), (1, 0, 0)] # calculate diff equation wt/w tf. res = ODE.solve_ode(x, fx, coeffs, bd_cond, ibtf) res_ref = ODE.solve_ode(r, fx, coeffs, bd_cond) assert_allclose(res(x)[0], res_ref(r)[0], atol=1e-4)
def test_becke_integral(self): """Test transform integral.""" oned = GaussLegendre(20) btf = BeckeRTransform(0.00001, 1.0) rad = btf.transform_1d_grid(oned) def gauss(x): return np.exp(-(x**2)) result = rad.integrate(gauss(rad.points)) ref_result = np.sqrt(np.pi) / 2 assert_almost_equal(result, ref_result, decimal=5) oned = GaussChebyshev(20) rad = btf.transform_1d_grid(oned) result = rad.integrate(gauss(rad.points)) assert_almost_equal(result, ref_result, decimal=3)
def test_domain(self): """Test domain errors.""" rad = UniformInteger(10) with self.assertRaises(ValueError): tf = BeckeRTransform(0.1, 1.2) tf.transform_1d_grid(rad) with self.assertRaises(ValueError): tf = HandyModRTransform(0.1, 10.0, 2) tf.transform_1d_grid(rad) with self.assertRaises(ValueError): tf = KnowlesRTransform(0.1, 1.2, 2) tf.transform_1d_grid(rad) with self.assertRaises(ValueError): tf = LinearFiniteRTransform(0.1, 10) tf.transform_1d_grid(rad) with self.assertRaises(ValueError): tf = MultiExpRTransform(0.1, 1.2) tf.transform_1d_grid(rad)
def test_error_raises(): """Test proper error raises.""" x = np.linspace(-0.999, 0.999, 20) # r = btf.transform(x) def fx(x): return 1 / x**2 coeffs = [-1, -2, 1] bd_cond = [(0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0)] # Test the error that the number of boundary conditions should be equal to order. assert_raises(ValueError, solve_ode, x, fx, coeffs, bd_cond[3:]) assert_raises(ValueError, solve_ode, x, fx, coeffs, bd_cond) test_coeff = [1, 2, 3, 4, 5] assert_raises(ValueError, solve_ode, x, fx, test_coeff, bd_cond) test_coeff = [1, 2, 3, 3] tf = BeckeRTransform(0.1, 1) assert_raises(ValueError, solve_ode, x, fx, test_coeff, bd_cond[:3], tf)
def test_cubicspline_and_interp_gauss(self): """Test cubicspline interpolation values.""" oned = GaussLegendre(30) btf = BeckeRTransform(0.0001, 1.5) rad = btf.transform_1d_grid(oned) atgrid = AtomGrid.from_pruned(rad, 1, sectors_r=[], sectors_degree=[7]) value_array = self.helper_func_gauss(atgrid.points) # random test points on gauss function for _ in range(20): r = np.random.rand(1)[0] * 2 theta = np.random.rand(10) phi = np.random.rand(10) x = r * np.sin(phi) * np.cos(theta) y = r * np.sin(phi) * np.sin(theta) z = r * np.cos(phi) input_points = np.array((x, y, z)).T interfunc = atgrid.interpolate(value_array) assert_allclose(self.helper_func_gauss(input_points), interfunc(input_points), atol=1e-4)
def test_cubicspline_and_interp_gauss(self): """Test cubicspline interpolation values.""" oned = GaussLegendre(30) btf = BeckeRTransform(0.0001, 1.5) rad = btf.transform_1d_grid(oned) atgrid = AtomGrid.from_pruned(rad, 1, sectors_r=[], sectors_degree=[7]) value_array = self.helper_func_gauss(atgrid.points) result = spline_with_atomic_grid(atgrid, value_array) # random test points on gauss function for _ in range(20): r = np.random.rand(1)[0] * 2 theta = np.random.rand(10) phi = np.random.rand(10) inters = interpolate_given_splines(result, r, theta, phi) x = r * np.sin(phi) * np.cos(theta) y = r * np.sin(phi) * np.sin(theta) z = r * np.cos(phi) assert_allclose(self.helper_func_gauss(np.array([x, y, z]).T), inters, atol=1e-4)
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_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_becke_infinite(self): """Test becke transformation when inf generated.""" inf_array = np.linspace(-1, 1, 21) R = BeckeRTransform.find_parameter(inf_array, 0.1, 1.2) btf = BeckeRTransform(0.1, R, trim_inf=True) tf_array = btf.transform(inf_array) inv_array = btf.inverse(tf_array) assert_allclose(inv_array, inf_array) # extra test for neg inf # test for number result = btf._convert_inf(-np.inf) assert_almost_equal(result, -1e16) result = btf._convert_inf(np.inf) assert_almost_equal(result, 1e16) # test for array test_array = np.random.rand(5) test_array[3] = -np.inf result = btf._convert_inf(test_array) assert_almost_equal(result[3], -1e16) test_array[3] = np.inf result = btf._convert_inf(test_array) assert_almost_equal(result[3], 1e16)
"""Compute 3rd order deriv of TF.""" return (self._exp - 2) * (self._exp - 1) * (self._exp) * x**(self._exp - 3) @pytest.mark.parametrize( "transform, fx, coeffs", [ [IdentityRTransform(), fx_ones, [-1, 1, 1]], [SqTF(), fx_ones, np.random.uniform(-100, 100, (3, ))], [ KnowlesRTransform(0.01, 1, 5), fx_ones, np.random.uniform(-10, 10, (3, )) ], [ BeckeRTransform(0.1, 100.0), fx_ones, np.random.uniform(0, 100, (3, )) ], [SqTF(1, 3), fx_complicated_example, np.random.uniform(0, 100, (3, ))], [SqTF(3, 1), fx_complicated_example, [2, 3, 2]], [SqTF(), fx_quadratic, np.random.uniform(-100, 100, (3, ))], [ SqTF(1, 4), fx_complicated_example, np.random.uniform(-10, 10, (3, )) ], [SqTF(1, 4), fx_complicated_example2, [1, -1, 1]], ], ) def test_transform_and_rearrange_to_explicit_ode_with_simple_boundary(
def test_error_raises(self): """Tests for error raises.""" with self.assertRaises(TypeError): AtomGrid.from_pruned(np.arange(3), 1.0, sectors_r=np.arange(2), sectors_degree=np.arange(3)) with self.assertRaises(ValueError): AtomGrid.from_pruned( OneDGrid(np.arange(3), np.arange(3)), radius=1.0, sectors_r=np.arange(2), sectors_degree=np.arange(0), ) with self.assertRaises(ValueError): AtomGrid.from_pruned( OneDGrid(np.arange(3), np.arange(3)), radius=1.0, sectors_r=np.arange(2), sectors_degree=np.arange(4), ) with self.assertRaises(ValueError): AtomGrid._generate_atomic_grid( OneDGrid(np.arange(3), np.arange(3)), np.arange(2)) with self.assertRaises(ValueError): AtomGrid.from_pruned( OneDGrid(np.arange(3), np.arange(3)), radius=1.0, sectors_r=np.array([0.3, 0.5, 0.7]), sectors_degree=np.array([3, 5, 7, 5]), center=np.array([0, 0, 0, 0]), ) # test preset with self.assertRaises(ValueError): AtomGrid.from_preset(atnum=1, preset="fine") with self.assertRaises(TypeError): AtomGrid(OneDGrid(np.arange(3), np.arange(3)), sizes=110) with self.assertRaises(TypeError): AtomGrid(OneDGrid(np.arange(3), np.arange(3)), degrees=17) with self.assertRaises(ValueError): AtomGrid(OneDGrid(np.arange(3), np.arange(3)), degrees=[17], rotate=-1) with self.assertRaises(TypeError): AtomGrid(OneDGrid(np.arange(3), np.arange(3)), degrees=[17], rotate="asdfaf") # error of radial grid with self.assertRaises(TypeError): AtomGrid(Grid(np.arange(1, 5, 1), np.ones(4)), degrees=[2, 3, 4, 5]) with self.assertRaises(TypeError): AtomGrid(OneDGrid(np.arange(-2, 2, 1), np.ones(4)), degrees=[2, 3, 4, 5]) with self.assertRaises(TypeError): rgrid = OneDGrid(np.arange(1, 3, 1), np.ones(2), domain=(-1, 5)) AtomGrid(rgrid, degrees=[2]) with self.assertRaises(TypeError): rgrid = OneDGrid(np.arange(-1, 1, 1), np.ones(2)) AtomGrid(rgrid, degrees=[2]) with self.assertRaises(ValueError): oned = GaussLegendre(30) btf = BeckeRTransform(0.0001, 1.5) rad = btf.transform_1d_grid(oned) atgrid = AtomGrid.from_preset(rad, atnum=1, preset="fine") atgrid.radial_component_splines(np.random.rand(100))
def test_becke_deriv(self): """Test becke transform derivatives with finite diff.""" btf = BeckeRTransform(0.1, 1.1) # call finite diff test function with given arrays self._deriv_finite_diff(-1, 0.90, btf)
def test_becke_inverse(self): """Test inverse transform basic function.""" btf = BeckeRTransform(0.1, 1.1) inv = InverseRTransform(btf) new_array = inv.transform(btf.transform(self.array)) assert_allclose(new_array, self.array)
def test_becke_inverse_deriv(self): """Test inverse transformation derivatives with finite diff.""" btf = BeckeRTransform(0.1, 1.1) inv = InverseRTransform(btf) self._deriv_finite_diff(0, 20, inv)
def test_becke_inverse_inverse(self): """Test inverse of inverse of Becke transformation.""" btf = BeckeRTransform(0.1, 1.1) inv = InverseRTransform(btf) inv_inv = inv.inverse(inv.transform(self.array)) assert_allclose(inv_inv, self.array, atol=1e-7)
def test_poisson_solve(self): """Test the poisson solve function.""" oned = GaussChebyshev(30) 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, ) # test splines project fit gauss function well def gauss(r): return np.exp(-(r**2)) for _ in range(20): coors = np.random.rand(10, 3) r = np.linalg.norm(coors, axis=-1) spl_0_0 = spls_mt[0, 0] interp_v = spl_0_0(r) ref_v = gauss(r) * np.sqrt(4 * np.pi) # 0.28209479 is the value in spherical harmonic Z_0_0 assert_allclose(interp_v, ref_v, atol=1e-3) ibtf = InverseRTransform(btf) linsp = np.linspace(-1, 0.99, 50) bound = p_0 * np.sqrt(4 * np.pi) res_bv = Poisson.solve_poisson_bv(spls_mt[0, 0], linsp, bound, tfm=ibtf) 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) long_rg_pts = np.array([2, 3, 4, 5, 6, 7, 8, 9, 10]) long_tf_pts = ibtf.transform(long_rg_pts) short_res = res_bv(near_tf_pts)[0] / near_rg_pts / (2 * np.sqrt(np.pi)) long_res = res_bv(long_tf_pts)[0] / long_rg_pts / (2 * np.sqrt(np.pi)) # ref are calculated with mathemetical # integrate[exp[-x^2 - y^2 - z^2] / sqrt[(x - a)^2 + y^2 +z^2], range] 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 ] ref_long_res = [ 2.77108, # 2 1.85601, # 3 1.39203, # 4 1.11362, # 5 0.92802, # 6 0.79544, # 7 0.69601, # 8 0.61867, # 9 0.55680, # 10 ] assert_allclose(short_res, ref_short_res, atol=5e-4) assert_allclose(long_res, ref_long_res, atol=5e-4) # solve same poisson equation with gauss directly gauss_pts = btf.transform(linsp) res_gs = Poisson.solve_poisson_bv(gauss, gauss_pts, p_0) gs_int_short = res_gs(near_rg_pts)[0] / near_rg_pts gs_int_long = res_gs(long_rg_pts)[0] / long_rg_pts assert_allclose(gs_int_short, ref_short_res, 5e-4) assert_allclose(gs_int_long, ref_long_res, 5e-4)
def test_becke_tf(self): """Test Becke initializaiton.""" btf = BeckeRTransform(0.1, 1.2) assert btf.R == 1.2 assert btf.rmin == 0.1