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_discretise_spatial_variable(self): # create discretisation mesh = get_mesh_for_testing() spatial_method = pybamm.SpatialMethod() spatial_method.build(mesh) # centre x1 = pybamm.SpatialVariable("x", ["negative electrode"]) x2 = pybamm.SpatialVariable("x", ["negative electrode", "separator"]) r = pybamm.SpatialVariable("r", ["negative particle"]) for var in [x1, x2, r]: var_disc = spatial_method.spatial_variable(var) self.assertIsInstance(var_disc, pybamm.Vector) np.testing.assert_array_equal( var_disc.evaluate()[:, 0], mesh.combine_submeshes(*var.domain)[0].nodes ) # edges x1_edge = pybamm.SpatialVariableEdge("x", ["negative electrode"]) x2_edge = pybamm.SpatialVariableEdge("x", ["negative electrode", "separator"]) r_edge = pybamm.SpatialVariableEdge("r", ["negative particle"]) for var in [x1_edge, x2_edge, r_edge]: var_disc = spatial_method.spatial_variable(var) self.assertIsInstance(var_disc, pybamm.Vector) np.testing.assert_array_equal( var_disc.evaluate()[:, 0], mesh.combine_submeshes(*var.domain)[0].edges )
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_basics(self): mesh = get_mesh_for_testing() spatial_method = pybamm.SpatialMethod(mesh) self.assertEqual(spatial_method.mesh, mesh) with self.assertRaises(NotImplementedError): spatial_method.gradient(None, None, None) with self.assertRaises(NotImplementedError): spatial_method.divergence(None, None, None) with self.assertRaises(NotImplementedError): spatial_method.laplacian(None, None, None) with self.assertRaises(NotImplementedError): spatial_method.gradient_squared(None, None, None) with self.assertRaises(NotImplementedError): spatial_method.integral(None, None) with self.assertRaises(NotImplementedError): spatial_method.indefinite_integral(None, None) with self.assertRaises(NotImplementedError): spatial_method.boundary_integral(None, None, None) with self.assertRaises(NotImplementedError): spatial_method.delta_function(None, None) with self.assertRaises(NotImplementedError): spatial_method.internal_neumann_condition(None, None, None, None)
def test_process_symbol_base(self): # create discretisation mesh = get_mesh_for_testing() spatial_methods = { "macroscale": pybamm.SpatialMethod(), "negative particle": pybamm.SpatialMethod(), "positive particle": pybamm.SpatialMethod(), "current collector": pybamm.SpatialMethod(), } disc = pybamm.Discretisation(mesh, spatial_methods) # variable var = pybamm.Variable("var") var_vec = pybamm.Variable("var vec", domain=["negative electrode"]) disc.y_slices = {var.id: [slice(53)], var_vec.id: [slice(53, 93)]} var_disc = disc.process_symbol(var) self.assertIsInstance(var_disc, pybamm.StateVector) self.assertEqual(var_disc.y_slices[0], disc.y_slices[var.id][0]) # variable dot var_dot = pybamm.VariableDot("var'") var_dot_disc = disc.process_symbol(var_dot) self.assertIsInstance(var_dot_disc, pybamm.StateVectorDot) self.assertEqual(var_dot_disc.y_slices[0], disc.y_slices[var.id][0]) # scalar scal = pybamm.Scalar(5) scal_disc = disc.process_symbol(scal) self.assertIsInstance(scal_disc, pybamm.Scalar) self.assertEqual(scal_disc.value, scal.value) # vector vec = pybamm.Vector(np.array([1, 2, 3, 4])) vec_disc = disc.process_symbol(vec) self.assertIsInstance(vec_disc, pybamm.Vector) np.testing.assert_array_equal(vec_disc.entries, vec.entries) # matrix mat = pybamm.Matrix(np.array([[1, 2, 3, 4], [5, 6, 7, 8]])) mat_disc = disc.process_symbol(mat) self.assertIsInstance(mat_disc, pybamm.Matrix) np.testing.assert_array_equal(mat_disc.entries, mat.entries) # binary operator bin = var + scal bin_disc = disc.process_symbol(bin) self.assertIsInstance(bin_disc, pybamm.Addition) self.assertIsInstance(bin_disc.children[0], pybamm.StateVector) self.assertIsInstance(bin_disc.children[1], pybamm.Scalar) bin2 = scal + var bin2_disc = disc.process_symbol(bin2) self.assertIsInstance(bin2_disc, pybamm.Addition) self.assertIsInstance(bin2_disc.children[0], pybamm.Scalar) self.assertIsInstance(bin2_disc.children[1], pybamm.StateVector) # non-spatial unary operator un1 = -var un1_disc = disc.process_symbol(un1) self.assertIsInstance(un1_disc, pybamm.Negate) self.assertIsInstance(un1_disc.children[0], pybamm.StateVector) un2 = abs(var) un2_disc = disc.process_symbol(un2) self.assertIsInstance(un2_disc, pybamm.AbsoluteValue) self.assertIsInstance(un2_disc.children[0], pybamm.StateVector) # function of one variable def myfun(x): return np.exp(x) func = pybamm.Function(myfun, var) func_disc = disc.process_symbol(func) self.assertIsInstance(func_disc, pybamm.Function) self.assertIsInstance(func_disc.children[0], pybamm.StateVector) func = pybamm.Function(myfun, scal) func_disc = disc.process_symbol(func) self.assertIsInstance(func_disc, pybamm.Function) self.assertIsInstance(func_disc.children[0], pybamm.Scalar) # function of multiple variables def myfun(x, y): return np.exp(x) * y func = pybamm.Function(myfun, var, scal) func_disc = disc.process_symbol(func) self.assertIsInstance(func_disc, pybamm.Function) self.assertIsInstance(func_disc.children[0], pybamm.StateVector) self.assertIsInstance(func_disc.children[1], pybamm.Scalar) # boundary value bv_left = pybamm.BoundaryValue(var_vec, "left") bv_left_disc = disc.process_symbol(bv_left) self.assertIsInstance(bv_left_disc, pybamm.MatrixMultiplication) self.assertIsInstance(bv_left_disc.left, pybamm.Matrix) self.assertIsInstance(bv_left_disc.right, pybamm.StateVector) bv_right = pybamm.BoundaryValue(var_vec, "left") bv_right_disc = disc.process_symbol(bv_right) self.assertIsInstance(bv_right_disc, pybamm.MatrixMultiplication) self.assertIsInstance(bv_right_disc.left, pybamm.Matrix) self.assertIsInstance(bv_right_disc.right, pybamm.StateVector) # not implemented sym = pybamm.Symbol("sym") with self.assertRaises(NotImplementedError): disc.process_symbol(sym)