def test_get_auxiliary_domain_repeats(self): # Test the method to read number of repeats from auxiliary domains mesh = get_1p1d_mesh_for_testing() spatial_method = pybamm.SpatialMethod() spatial_method.build(mesh) # No auxiliary domains repeats = spatial_method._get_auxiliary_domain_repeats({}) self.assertEqual(repeats, 1) # Just secondary domain repeats = spatial_method._get_auxiliary_domain_repeats( {"secondary": ["negative electrode"]}) self.assertEqual(repeats, mesh["negative electrode"].npts) repeats = spatial_method._get_auxiliary_domain_repeats( {"secondary": ["negative electrode", "separator"]}) self.assertEqual( repeats, mesh["negative electrode"].npts + mesh["separator"].npts) # Just tertiary domain repeats = spatial_method._get_auxiliary_domain_repeats({ "secondary": ["negative electrode", "separator"], "tertiary": ["current collector"], }) self.assertEqual( repeats, (mesh["negative electrode"].npts + mesh["separator"].npts) * mesh["current collector"].npts, )
def test_grad_1plus1d(self): mesh = get_1p1d_mesh_for_testing() spatial_methods = {"macroscale": pybamm.FiniteVolume()} disc = pybamm.Discretisation(mesh, spatial_methods) a = pybamm.Variable("a", domain=["negative electrode"]) b = pybamm.Variable("b", domain=["separator"]) c = pybamm.Variable("c", domain=["positive electrode"]) var = pybamm.Concatenation(a, b, c) boundary_conditions = { var.id: { "left": (pybamm.Vector(np.linspace(0, 1, 15)), "Neumann"), "right": (pybamm.Vector(np.linspace(0, 1, 15)), "Neumann"), } } disc.bcs = boundary_conditions disc.set_variable_slices([var]) grad_eqn_disc = disc.process_symbol(pybamm.grad(var)) # Evaulate combined_submesh = mesh.combine_submeshes(*var.domain) linear_y = np.outer(np.linspace(0, 1, 15), combined_submesh[0].nodes).reshape(-1, 1) expected = np.outer(np.linspace(0, 1, 15), np.ones_like(combined_submesh[0].edges)).reshape( -1, 1) np.testing.assert_array_almost_equal( grad_eqn_disc.evaluate(None, linear_y), expected)
def test_neg_pos_bcs(self): # 2d macroscale mesh = get_1p1d_mesh_for_testing() spatial_methods = { "macroscale": pybamm.FiniteVolume(), "negative particle": pybamm.FiniteVolume(), "positive particle": pybamm.FiniteVolume(), "current collector": pybamm.FiniteVolume(), } disc = pybamm.Discretisation(mesh, spatial_methods) # var var = pybamm.Variable("var", domain="current collector") disc.set_variable_slices([var]) # grad grad_eqn = pybamm.grad(var) # bcs (on each tab) boundary_conditions = { var.id: { "negative tab": (pybamm.Scalar(1), "Dirichlet"), "positive tab": (pybamm.Scalar(0), "Neumann"), "no tab": (pybamm.Scalar(8), "Dirichlet"), } } disc.bcs = boundary_conditions # check after disc that negative tab goes to left and positive tab goes # to right disc.process_symbol(grad_eqn) self.assertEqual(disc.bcs[var.id]["left"][0].id, pybamm.Scalar(1).id) self.assertEqual(disc.bcs[var.id]["left"][1], "Dirichlet") self.assertEqual(disc.bcs[var.id]["right"][0].id, pybamm.Scalar(0).id) self.assertEqual(disc.bcs[var.id]["right"][1], "Neumann")
def test_grad_div_with_bcs_on_tab(self): # 2d macroscale mesh = get_1p1d_mesh_for_testing() spatial_methods = { "macroscale": pybamm.FiniteVolume(), "negative particle": pybamm.FiniteVolume(), "positive particle": pybamm.FiniteVolume(), "current collector": pybamm.FiniteVolume(), } disc = pybamm.Discretisation(mesh, spatial_methods) y_test = np.ones(mesh["current collector"][0].npts) # var var = pybamm.Variable("var", domain="current collector") disc.set_variable_slices([var]) # grad grad_eqn = pybamm.grad(var) # div N = pybamm.grad(var) div_eqn = pybamm.div(N) # bcs (on each tab) boundary_conditions = { var.id: { "negative tab": (pybamm.Scalar(1), "Dirichlet"), "positive tab": (pybamm.Scalar(0), "Neumann"), } } disc.bcs = boundary_conditions grad_eqn_disc = disc.process_symbol(grad_eqn) grad_eqn_disc.evaluate(None, y_test) div_eqn_disc = disc.process_symbol(div_eqn) div_eqn_disc.evaluate(None, y_test) # bcs (one pos, one not tab) boundary_conditions = { var.id: { "no tab": (pybamm.Scalar(1), "Dirichlet"), "positive tab": (pybamm.Scalar(0), "Dirichlet"), } } disc.bcs = boundary_conditions grad_eqn_disc = disc.process_symbol(grad_eqn) grad_eqn_disc.evaluate(None, y_test) div_eqn_disc = disc.process_symbol(div_eqn) div_eqn_disc.evaluate(None, y_test) # bcs (one neg, one not tab) boundary_conditions = { var.id: { "negative tab": (pybamm.Scalar(1), "Neumann"), "no tab": (pybamm.Scalar(0), "Neumann"), } } disc.bcs = boundary_conditions grad_eqn_disc = disc.process_symbol(grad_eqn) grad_eqn_disc.evaluate(None, y_test) div_eqn_disc = disc.process_symbol(div_eqn) div_eqn_disc.evaluate(None, y_test)
def test_broadcast_checks(self): child = pybamm.Symbol("sym", domain=["negative electrode"]) symbol = pybamm.BoundaryGradient(child, "left") mesh = get_mesh_for_testing() spatial_method = pybamm.SpatialMethod() spatial_method.build(mesh) with self.assertRaisesRegex(TypeError, "Cannot process BoundaryGradient"): spatial_method.boundary_value_or_flux(symbol, child) mesh = get_1p1d_mesh_for_testing() spatial_method = pybamm.SpatialMethod() spatial_method.build(mesh) with self.assertRaisesRegex(NotImplementedError, "Cannot process 2D symbol"): spatial_method.boundary_value_or_flux(symbol, child)
def test_extrapolate_2d_models(self): # create discretisation mesh = get_p2d_mesh_for_testing() method_options = { "extrapolation": { "order": "linear", "use bcs": False } } spatial_methods = { "macroscale": pybamm.FiniteVolume(method_options), "negative particle": pybamm.FiniteVolume(method_options), "positive particle": pybamm.FiniteVolume(method_options), "current collector": pybamm.FiniteVolume(method_options), } disc = pybamm.Discretisation(mesh, spatial_methods) # Microscale var = pybamm.Variable("var", domain="negative particle") extrap_right = pybamm.BoundaryValue(var, "right") disc.set_variable_slices([var]) extrap_right_disc = disc.process_symbol(extrap_right) self.assertEqual(extrap_right_disc.domain, []) # domain for boundary values must now be explicitly set extrap_right.domain = ["negative electrode"] disc.set_variable_slices([var]) extrap_right_disc = disc.process_symbol(extrap_right) self.assertEqual(extrap_right_disc.domain, ["negative electrode"]) # evaluate y_macro = mesh["negative electrode"][0].nodes y_micro = mesh["negative particle"][0].nodes y = np.outer(y_macro, y_micro).reshape(-1, 1) # extrapolate to r=1 --> should evaluate to y_macro np.testing.assert_array_almost_equal( extrap_right_disc.evaluate(y=y)[:, 0], y_macro) var = pybamm.Variable("var", domain="positive particle") extrap_right = pybamm.BoundaryValue(var, "right") disc.set_variable_slices([var]) extrap_right_disc = disc.process_symbol(extrap_right) self.assertEqual(extrap_right_disc.domain, []) # domain for boundary values must now be explicitly set extrap_right.domain = ["positive electrode"] disc.set_variable_slices([var]) extrap_right_disc = disc.process_symbol(extrap_right) self.assertEqual(extrap_right_disc.domain, ["positive electrode"]) # 2d macroscale mesh = get_1p1d_mesh_for_testing() disc = pybamm.Discretisation(mesh, spatial_methods) var = pybamm.Variable("var", domain="negative electrode") extrap_right = pybamm.BoundaryValue(var, "right") disc.set_variable_slices([var]) extrap_right_disc = disc.process_symbol(extrap_right) self.assertEqual(extrap_right_disc.domain, []) # test extrapolate to "negative tab" gives same as "left" and # "positive tab" gives same "right" (see get_mesh_for_testing) var = pybamm.Variable("var", domain="current collector") disc.set_variable_slices([var]) submesh = mesh["current collector"] constant_y = np.ones_like(submesh[0].nodes[:, np.newaxis]) extrap_neg = pybamm.BoundaryValue(var, "negative tab") extrap_neg_disc = disc.process_symbol(extrap_neg) extrap_left = pybamm.BoundaryValue(var, "left") extrap_left_disc = disc.process_symbol(extrap_left) np.testing.assert_array_equal( extrap_neg_disc.evaluate(None, constant_y), extrap_left_disc.evaluate(None, constant_y), ) extrap_pos = pybamm.BoundaryValue(var, "positive tab") extrap_pos_disc = disc.process_symbol(extrap_pos) extrap_right = pybamm.BoundaryValue(var, "right") extrap_right_disc = disc.process_symbol(extrap_right) np.testing.assert_array_equal( extrap_pos_disc.evaluate(None, constant_y), extrap_right_disc.evaluate(None, constant_y), )