def iter_grids(): """generator providing some test grids""" for periodic in [True, False]: yield grids.UnitGrid([3], periodic=periodic) yield grids.UnitGrid([3, 3, 3], periodic=periodic) yield grids.CartesianGrid([[-1, 2], [0, 3]], [5, 7], periodic=periodic) yield grids.CylindricalSymGrid(3, [-1, 2], [7, 8], periodic_z=periodic) yield grids.PolarSymGrid(3, 4) yield grids.SphericalSymGrid(3, 4)
def test_grid_plotting(): """test plotting of grids""" grids.UnitGrid([4]).plot() grids.UnitGrid([4, 4]).plot() with pytest.raises(NotImplementedError): grids.UnitGrid([4, 4, 4]).plot() grids.PolarSymGrid(4, 8).plot() grids.PolarSymGrid((2, 4), 8).plot()
def test_pde_wrong_input(): """test some wrong input""" with pytest.raises(ValueError): PDE({"t": 1}) with pytest.raises(ValueError): PDE({"E": 1}) with pytest.raises(ValueError): PDE({"E": 1, "t": 0}) grid = grids.UnitGrid([4]) eq = PDE({"u": 1}) assert eq.expressions == {"u": "1.0"} with pytest.raises(ValueError): eq.evolution_rate(FieldCollection.scalar_random_uniform(2, grid)) eq = PDE({"u": 1, "v": 2}) assert eq.expressions == {"u": "1.0", "v": "2.0"} with pytest.raises(ValueError): eq.evolution_rate(ScalarField.random_uniform(grid)) eq = PDE({"u": "a"}) with pytest.raises(RuntimeError): eq.evolution_rate(ScalarField.random_uniform(grid)) eq = PDE({"x": "x"}) with pytest.raises(ValueError): eq.evolution_rate(ScalarField(grid))
def iter_grids(): """generate some test grids""" yield grids.UnitGrid([2, 2], periodic=[True, False]) yield grids.CartesianGrid([[0, 1]], [2], periodic=[False]) yield grids.CylindricalSymGrid(2, (0, 2), (2, 2), periodic_z=True) yield grids.SphericalSymGrid(2, 2) yield grids.PolarSymGrid(2, 2)
def test_pde_critical_input(): """test some wrong input and edge cases""" # test whether reserved symbols can be used as variables grid = grids.UnitGrid([4]) eq = PDE({"E": 1}) res = eq.solve(ScalarField(grid), t_range=2) np.testing.assert_allclose(res.data, 2) with pytest.raises(ValueError): PDE({"t": 1}) eq = PDE({"u": 1}) assert eq.expressions == {"u": "1.0"} with pytest.raises(ValueError): eq.evolution_rate(FieldCollection.scalar_random_uniform(2, grid)) eq = PDE({"u": 1, "v": 2}) assert eq.expressions == {"u": "1.0", "v": "2.0"} with pytest.raises(ValueError): eq.evolution_rate(ScalarField.random_uniform(grid)) eq = PDE({"u": "a"}) with pytest.raises(RuntimeError): eq.evolution_rate(ScalarField.random_uniform(grid)) eq = PDE({"x": "x"}) with pytest.raises(ValueError): eq.evolution_rate(ScalarField(grid))
def test_pde_bcs_error(bc): """test PDE with wrong boundary conditions""" eq = PDE({"u": "laplace(u)"}, bc=bc) grid = grids.UnitGrid([8, 8]) field = ScalarField.random_normal(grid) for backend in ["numpy", "numba"]: with pytest.raises(BCDataError): eq.solve(field, t_range=1, dt=0.01, backend=backend, tracker=None)
def test_pde_user_funcs(): """test user supplied functions""" # test a simple case eq = PDE({"u": "get_x(gradient(u))"}, user_funcs={"get_x": lambda arr: arr[0]}) field = ScalarField.random_colored(grids.UnitGrid([32, 32])) rhs = eq.evolution_rate(field) np.testing.assert_allclose(rhs.data, field.gradient("natural").data[0]) f = eq._make_pde_rhs_numba(field) np.testing.assert_allclose(f(field.data, 0), field.gradient("natural").data[0])
def test_pde_product_operators(): """test inner and outer products""" eq = PDE( {"p": "gradient(dot(p, p) + inner(p, p)) + tensor_divergence(outer(p, p))"} ) assert not eq.explicit_time_dependence assert not eq.complex_valued field = VectorField(grids.UnitGrid([4]), 1) res = eq.solve(field, t_range=1, dt=0.1, backend="numpy", tracker=None) np.testing.assert_allclose(res.data, field.data)
def iter_grids(): """helper function iterating over different grids""" for periodic in [True, False]: yield grids.UnitGrid([3, 4], periodic=periodic) yield grids.CartesianGrid([[0, 1], [-2, 3]], [4, 5], periodic=periodic) yield grids.CylindricalSymGrid(3, [-1, 2], [5, 7], periodic_z=periodic) yield grids.SphericalSymGrid(4, 6) yield grids.PolarSymGrid(4, 5)
def test_pde_time_dependent_bcs(backend): """test PDE with time-dependent BCs""" field = ScalarField(grids.UnitGrid([3])) eq = PDE({"c": "laplace(c)"}, bc={"value_expression": "Heaviside(t - 1.5)"}) storage = MemoryStorage() eq.solve(field, t_range=10, dt=1e-2, backend=backend, tracker=storage.tracker(1)) np.testing.assert_allclose(storage[1].data, 0) np.testing.assert_allclose(storage[-1].data, 1, rtol=1e-3)
def test_pde_vector(): """test PDE with a single vector field""" eq = PDE({"u": "vector_laplace(u) + exp(-t)"}) assert eq.explicit_time_dependence assert not eq.complex_valued grid = grids.UnitGrid([8, 8]) field = VectorField.random_normal(grid) res_a = eq.solve(field, t_range=1, dt=0.01, backend="numpy", tracker=None) res_b = eq.solve(field, t_range=1, dt=0.01, backend="numba", tracker=None) res_a.assert_field_compatible(res_b) np.testing.assert_allclose(res_a.data, res_b.data)
def test_pde_2scalar(): """test PDE with two scalar fields""" eq = PDE({"u": "laplace(u) - u", "v": "- u * v"}) assert not eq.explicit_time_dependence assert not eq.complex_valued grid = grids.UnitGrid([8]) field = FieldCollection.scalar_random_uniform(2, grid) res_a = eq.solve(field, t_range=1, dt=0.01, backend="numpy", tracker=None) res_b = eq.solve(field, t_range=1, dt=0.01, backend="numba", tracker=None) res_a.assert_field_compatible(res_b) np.testing.assert_allclose(res_a.data, res_b.data)
def test_pde_bcs(bc): """test PDE with boundary conditions""" eq = PDE({"u": "laplace(u)"}, bc=bc) assert not eq.explicit_time_dependence assert not eq.complex_valued grid = grids.UnitGrid([8]) field = ScalarField.random_normal(grid) res_a = eq.solve(field, t_range=1, dt=0.01, backend="numpy", tracker=None) res_b = eq.solve(field, t_range=1, dt=0.01, backend="numba", tracker=None) res_a.assert_field_compatible(res_b) np.testing.assert_allclose(res_a.data, res_b.data)
def test_pde_complex(): """test complex valued PDE""" eq = PDE({"p": "I * laplace(p)"}) assert not eq.explicit_time_dependence assert eq.complex_valued field = ScalarField.random_uniform(grids.UnitGrid([4])) assert not field.is_complex res1 = eq.solve(field, t_range=1, dt=0.1, backend="numpy", tracker=None) assert res1.is_complex res2 = eq.solve(field, t_range=1, dt=0.1, backend="numpy", tracker=None) assert res2.is_complex np.testing.assert_allclose(res1.data, res2.data)
def test_pde_spatial_args(): """ test ScalarFieldExpression without extra dependence """ eq = PDE({"a": "x"}) field = ScalarField(grids.UnitGrid([2])) rhs = eq.evolution_rate(field) assert rhs == field.copy(data=[0.5, 1.5]) rhs = eq.make_pde_rhs(field, backend="numba") np.testing.assert_allclose(rhs(field.data, 0.0), np.array([0.5, 1.5])) eq = PDE({"a": "x + y"}) with pytest.raises(RuntimeError): eq.evolution_rate(field)
def test_pde_integral(backend): """test PDE with integral""" grid = grids.UnitGrid([16]) field = ScalarField.random_uniform(grid) eq = PDE({"c": "-integral(c)"}) # test rhs rhs = eq.make_pde_rhs(field, backend=backend) np.testing.assert_allclose(rhs(field.data, 0), -field.integral) # test evolution for method in ["scipy", "explicit"]: res = eq.solve(field, t_range=1000, method=method, tracker=None) assert res.integral == pytest.approx(0, abs=1e-2) np.testing.assert_allclose(res.data, field.data - field.magnitude, atol=1e-3)
def test_pde_vector_scalar(): """test PDE with a vector and a scalar field""" eq = PDE({"u": "vector_laplace(u) - u + gradient(v)", "v": "- divergence(u)"}) assert not eq.explicit_time_dependence assert not eq.complex_valued grid = grids.UnitGrid([8, 8]) field = FieldCollection( [VectorField.random_uniform(grid), ScalarField.random_uniform(grid)] ) res_a = eq.solve(field, t_range=1, dt=0.01, backend="numpy", tracker=None) res_b = eq.solve(field, t_range=1, dt=0.01, backend="numba", tracker=None) res_a.assert_field_compatible(res_b) np.testing.assert_allclose(res_a.data, res_b.data)
def test_pde_noise(backend): """test noise operator on PDE class""" grid = grids.UnitGrid([64, 64]) state = FieldCollection([ScalarField(grid), ScalarField(grid)]) eq = PDE({"a": 0, "b": 0}, noise=0.5) res = eq.solve(state, t_range=1, backend=backend, dt=1, tracker=None) assert res.data.std() == pytest.approx(0.5, rel=0.1) eq = PDE({"a": 0, "b": 0}, noise=[0.01, 2.0]) res = eq.solve(state, t_range=1, backend=backend, dt=1) assert res.data[0].std() == pytest.approx(0.01, rel=0.1) assert res.data[1].std() == pytest.approx(2.0, rel=0.1) with pytest.raises(ValueError): eq = PDE({"a": 0}, noise=[0.01, 2.0]) eq.solve(ScalarField(grid), t_range=1, backend=backend, dt=1, tracker=None)
def test_pde_spatial_args(backend): """test PDE with spatial dependence""" field = ScalarField(grids.UnitGrid([2])) eq = PDE({"a": "x"}) rhs = eq.make_pde_rhs(field, backend=backend) np.testing.assert_allclose(rhs(field.data, 0.0), np.array([0.5, 1.5])) # test combination of spatial dependence and differential oeprators eq = PDE({"a": "dot(gradient(x), gradient(a))"}) rhs = eq.make_pde_rhs(field, backend=backend) np.testing.assert_allclose(rhs(field.data, 0.0), np.array([0.0, 0.0])) # test invalid spatial dependence eq = PDE({"a": "x + y"}) with pytest.raises(RuntimeError): rhs = eq.make_pde_rhs(field, backend=backend) rhs(field.data, 0.0)
def test_custom_operators(): """ test using a custom operator """ grid = grids.UnitGrid([32]) field = ScalarField.random_normal(grid) eq = PDE({"u": "undefined(u)"}) with pytest.raises(NameError): eq.evolution_rate(field) def make_op(state): return lambda state: state grids.UnitGrid.register_operator("undefined", make_op) eq._cache = {} # reset cache res = eq.evolution_rate(field) np.testing.assert_allclose(field.data, res.data) del grids.UnitGrid._operators["undefined"] # reset original state
def test_pde_consts(): """test using the consts argument in PDE""" field = ScalarField(grids.UnitGrid([3]), 1) eq = PDE({"a": "b"}, consts={"b": 2}) np.testing.assert_allclose(eq.evolution_rate(field).data, 2) eq = PDE({"a": "b**2"}, consts={"b": field}) np.testing.assert_allclose(eq.evolution_rate(field).data, field.data) eq = PDE({"a": "laplace(b)"}, consts={"b": field}) np.testing.assert_allclose(eq.evolution_rate(field).data, 0) eq = PDE({"a": "laplace(b)"}, consts={"b": 3}) with pytest.raises(Exception): eq.evolution_rate(field) eq = PDE({"a": "laplace(b)"}, consts={"b": field.data}) with pytest.raises(Exception): eq.evolution_rate(field)
def test_iter_mirror_points(): """test iterating mirror points in grids""" grid_cart = grids.UnitGrid([2, 2], periodic=[True, False]) grid_cyl = grids.CylindricalSymGrid(2, (0, 2), (2, 2), periodic_z=False) grid_sph = grids.SphericalSymGrid(2, 2) assert grid_cart._cache_hash() != grid_cyl._cache_hash( ) != grid_sph._cache_hash() for with_, only_periodic in itertools.product([False, True], repeat=2): num_expect = 2 if only_periodic else 8 num_expect += 1 if with_ else 0 ps = grid_cart.iter_mirror_points([1, 1], with_, only_periodic) assert len(list(ps)) == num_expect num_expect = 0 if only_periodic else 2 num_expect += 1 if with_ else 0 ps = grid_cyl.iter_mirror_points([0, 0, 1], with_, only_periodic) assert len(list(ps)) == num_expect num_expect = 1 if with_ else 0 ps = grid_sph.iter_mirror_points([0, 0, 0], with_, only_periodic) assert len(list(ps)) == num_expect