def test_setting_boundary_conditions(): """ test setting some boundary conditions """ grid = CylindricalGrid(1, [0, 1], 3) b_inner = NeumannBC(grid, 0, upper=False) assert grid.get_boundary_conditions("natural")[0].low == b_inner assert grid.get_boundary_conditions({"value": 2})[0].low != b_inner
def test_polar_conversion(periodic): """ test conversion to polar coordinates """ grid = CylindricalGrid(1, [-1, 1], [5, 5], periodic_z=periodic) dists = grid.polar_coordinates_real([0, 0, 0]) assert np.all(0.09 <= dists) assert np.any(dists < 0.11) assert np.all(dists <= np.sqrt(2)) assert np.any(dists > 0.8 * np.sqrt(2))
def test_cylindrical_grid(): """ test simple cylindrical grid """ for periodic in [True, False]: grid = CylindricalGrid(4, (-1, 2), (8, 9), periodic_z=periodic) msg = str(grid) assert grid.dim == 3 assert grid.numba_type == "f8[:, :]" assert grid.shape == (8, 9) assert grid.length == pytest.approx(3) assert grid.discretization[0] == pytest.approx(0.5) assert grid.discretization[1] == pytest.approx(1 / 3) np.testing.assert_array_equal(grid.discretization, np.array([0.5, 1 / 3])) assert not grid.uniform_cell_volumes assert grid.volume == pytest.approx(np.pi * 4 ** 2 * 3) assert grid.volume == pytest.approx(grid.integrate(1)) rs, zs = grid.axes_coords np.testing.assert_allclose(rs, np.linspace(0.25, 3.75, 8)) np.testing.assert_allclose(zs, np.linspace(-1 + 1 / 6, 2 - 1 / 6, 9)) # random points c = np.random.randint(8, size=(6, 2)) c1 = grid.point_to_cell(grid.cell_to_point(c)) np.testing.assert_almost_equal(c, c1, err_msg=msg) assert grid.contains_point(grid.get_random_point()) assert grid.contains_point(grid.get_random_point(1.49)) assert "laplace" in grid.operators
def test_laplace_cyl(): """ test the implementation of the laplace operator """ for boundary_z in ["periodic", "derivative"]: grid = CylindricalGrid(4, (0, 5), (8, 16), periodic_z=(boundary_z == "periodic")) a_2d = np.random.uniform(0, 1, grid.shape) bcs = grid.get_boundary_conditions(["derivative", boundary_z]) lap_2d = ops.make_laplace(bcs) b_2d = lap_2d(a_2d) assert b_2d.shape == grid.shape
def test_findiff_cyl(): """test operator for a simple cylindrical grid. Note that we only really test the polar symmetry""" grid = CylindricalGrid(1.5, [0, 1], (3, 2), periodic_z=True) _, r1, r2 = grid.axes_coords[0] np.testing.assert_array_equal(grid.discretization, np.full(2, 0.5)) s = ScalarField(grid, [[1, 1], [2, 2], [4, 4]]) v = VectorField(grid, [[[1, 1], [2, 2], [4, 4]], [[0, 0]] * 3, [[0, 0]] * 3]) # test gradient grad = s.gradient(bc=["value", "periodic"]) np.testing.assert_allclose(grad.data[0], [[1, 1], [3, 3], [-6, -6]]) grad = s.gradient(bc=["derivative", "periodic"]) np.testing.assert_allclose(grad.data[0], [[1, 1], [3, 3], [2, 2]]) # test divergence div = v.divergence(bc=["value", "periodic"]) y1 = 3 + 2 / r1 y2 = -6 + 4 / r2 np.testing.assert_allclose(div.data, [[5, 5], [y1, y1], [y2, y2]]) div = v.divergence(bc=["derivative", "periodic"]) y2 = 2 + 4 / r2 np.testing.assert_allclose(div.data, [[5, 5], [y1, y1], [y2, y2]]) # test laplace lap = s.laplace(bc=[{"type": "value", "value": 3}, "periodic"]) y1 = 4 + 3 / r1 y2 = -16 np.testing.assert_allclose(lap.data, [[8, 8], [y1, y1], [y2, y2]]) lap = s.laplace(bc=[{"type": "derivative", "value": 3}, "periodic"]) y2 = -2 + 3.5 / r2 np.testing.assert_allclose(lap.data, [[8, 8], [y1, y1], [y2, y2]])
def test_laplacian_field_cyl(): """ test the gradient operator """ grid = CylindricalGrid(2 * np.pi, [0, 2 * np.pi], [8, 16], periodic_z=True) r, z = grid.cell_coords[..., 0], grid.cell_coords[..., 1] s = ScalarField(grid, data=np.cos(r) + np.sin(z)) s_lap = s.laplace(bc="natural") assert s_lap.data.shape == (8, 16) res = -np.cos(r) - np.sin(r) / r - np.sin(z) np.testing.assert_allclose(s_lap.data, res, rtol=0.1, atol=0.1)
def iter_grids(): """ generator providing some test grids """ for periodic in [True, False]: yield UnitGrid([3], periodic=periodic) yield UnitGrid([3, 3, 3], periodic=periodic) yield CartesianGrid([[-1, 2], [0, 3]], [5, 7], periodic=periodic) yield CylindricalGrid(3, [-1, 2], [7, 8], periodic_z=periodic) yield PolarGrid(3, 4) yield SphericalGrid(3, 4)
def test_gradient_squared(): """ compare gradient squared operator """ grid = CylindricalGrid(2 * np.pi, [0, 2 * np.pi], 64) field = ScalarField.random_harmonic(grid, modes=1) s1 = field.gradient("natural").to_scalar("squared_sum") s2 = field.gradient_squared("natural", central=True) np.testing.assert_allclose(s1.data, s2.data, rtol=0.2, atol=0.2) s3 = field.gradient_squared("natural", central=False) np.testing.assert_allclose(s1.data, s3.data, rtol=0.2, atol=0.2) assert not np.array_equal(s2.data, s3.data)
def test_gradient_field_cyl(): """ test the gradient operator""" grid = CylindricalGrid(2 * np.pi, [0, 2 * np.pi], [8, 16], periodic_z=True) r, z = grid.cell_coords[..., 0], grid.cell_coords[..., 1] s = ScalarField(grid, data=np.cos(r) + np.sin(z)) v = s.gradient(bc="natural") assert v.data.shape == (3, 8, 16) np.testing.assert_allclose(v.data[0], -np.sin(r), rtol=0.1, atol=0.1) np.testing.assert_allclose(v.data[1], np.cos(z), rtol=0.1, atol=0.1) np.testing.assert_allclose(v.data[2], 0, rtol=0.1, atol=0.1)
def test_cylindrical_to_cartesian(): """ test conversion of cylindrical grid to Cartesian """ expr_cyl = "cos(z / 2) / (1 + r**2)" expr_cart = expr_cyl.replace("r**2", "(x**2 + y**2)") z_range = (-np.pi, 2 * np.pi) grid_cyl = CylindricalGrid(10, z_range, (16, 33)) pf_cyl = ScalarField.from_expression(grid_cyl, expression=expr_cyl) grid_cart = CartesianGrid([[-7, 7], [-6, 7], z_range], [16, 16, 16]) pf_cart1 = pf_cyl.interpolate_to_grid(grid_cart) pf_cart2 = ScalarField.from_expression(grid_cart, expression=expr_cart) np.testing.assert_allclose(pf_cart1.data, pf_cart2.data, atol=0.1)
def test_vector_gradient_divergence_field_cyl(): """ test the divergence operator """ grid = CylindricalGrid(2 * np.pi, [0, 2 * np.pi], [8, 16], periodic_z=True) r, z = grid.cell_coords[..., 0], grid.cell_coords[..., 1] data = [ np.cos(r) + np.sin(z)**2, np.cos(r)**2 + np.sin(z), np.zeros_like(r) ] v = VectorField(grid, data=data) t = v.gradient(bc="natural") assert t.data.shape == (3, 3, 8, 16) v = t.divergence(bc="natural") assert v.data.shape == (3, 8, 16)
def test_divergence_field_cyl(): """ test the divergence operator """ grid = CylindricalGrid(2 * np.pi, [0, 2 * np.pi], [8, 16], periodic_z=True) r, z = grid.cell_coords[..., 0], grid.cell_coords[..., 1] data = [ np.cos(r) + np.sin(z)**2, np.cos(r)**2 + np.sin(z), np.zeros_like(r) ] v = VectorField(grid, data=data) s = v.divergence(bc="natural") assert s.data.shape == (8, 16) res = np.cos(z) - np.sin(r) + (np.cos(r) + np.sin(z)**2) / r np.testing.assert_allclose(s.data, res, rtol=0.1, atol=0.1)
def test_grid_laplace(): """ test the cylindrical implementation of the laplace operator """ grid_cyl = CylindricalGrid(6, (0, 4), (4, 4)) grid_cart = CartesianGrid([[-5, 5], [-5, 5], [0, 4]], [10, 10, 4]) a_2d = ScalarField.from_expression(grid_cyl, expression="exp(-5 * r) * cos(z / 3)") a_3d = a_2d.interpolate_to_grid(grid_cart) b_2d = a_2d.laplace("natural") b_3d = a_3d.laplace("natural") b_2d_3 = b_2d.interpolate_to_grid(grid_cart) np.testing.assert_allclose(b_2d_3.data, b_3d.data, rtol=0.2, atol=0.2)
def test_grid_div_grad(): """ compare div grad to laplacian """ grid = CylindricalGrid(2 * np.pi, (0, 2 * np.pi), (16, 16), periodic_z=True) r, z = grid.cell_coords[..., 0], grid.cell_coords[..., 1] arr = np.cos(r) + np.sin(z) bcs = grid.get_boundary_conditions() laplace = grid.get_operator("laplace", bcs) grad = grid.get_operator("gradient", bcs) div = grid.get_operator("divergence", bcs.differentiated) a = laplace(arr) b = div(grad(arr)) res = (-np.sin(r) / r - np.cos(r)) - np.sin(z) # do not test the radial boundary points np.testing.assert_allclose(a[1:-1], res[1:-1], rtol=0.1, atol=0.05) np.testing.assert_allclose(b[1:-1], res[1:-1], rtol=0.1, atol=0.05)
""" Visualizing a scalar field ========================== This example displays methods for visualizing scalar fields. """ import numpy as np import matplotlib.pyplot as plt from pde import CylindricalGrid, ScalarField # create a scalar field with some noise grid = CylindricalGrid(7, [0, 4 * np.pi], 64) data = ScalarField.from_expression(grid, 'sin(z) * exp(-r / 3)') data += 0.05 * ScalarField.random_normal(grid) # manipulate the field smoothed = data.smooth() # Gaussian smoothing to get rid of the noise projected = data.project('r') # integrate along the radial direction sliced = smoothed.slice({'z': 1}) # slice the smoothed data # create four plots of the field and the modifications fig, axes = plt.subplots(nrows=2, ncols=2) data.plot(ax=axes[0, 0], title='Original field') smoothed.plot(ax=axes[1, 0], title='Smoothed field') projected.plot(ax=axes[0, 1], title='Projection on axial coordinate') sliced.plot(ax=axes[1, 1], title='Slice of smoothed field at $z=1$') plt.subplots_adjust(hspace=0.8)
""" Plotting a scalar field in cylindrical coordinates ================================================== This example shows how to initialize and visualize the scalar field :math:`u = \sqrt{z} \, \exp(-r^2)` in cylindrical coordinates. """ from pde import CylindricalGrid, ScalarField grid = CylindricalGrid(radius=3, bounds_z=[0, 4], shape=16) field = ScalarField.from_expression(grid, "sqrt(z) * exp(-r**2)") field.plot(title="Scalar field in cylindrical coordinates")
def test_setting_domain_cylindrical(): """ test various versions of settings bcs for cylindrical grids """ grid = CylindricalGrid(1, [0, 1], [2, 2], periodic_z=False) grid.get_boundary_conditions("natural") grid.get_boundary_conditions(["derivative", "derivative"]) with pytest.raises(ValueError): grid.get_boundary_conditions(["derivative"]) with pytest.raises(ValueError): grid.get_boundary_conditions(["derivative"] * 3) with pytest.raises(RuntimeError): grid.get_boundary_conditions(["derivative", "periodic"]) grid = CylindricalGrid(1, [0, 1], [2, 2], periodic_z=True) grid.get_boundary_conditions("natural") grid.get_boundary_conditions(["derivative", "periodic"]) with pytest.raises(RuntimeError): grid.get_boundary_conditions(["derivative", "derivative"])