def test_tab_left_right(self): # set variables and submesh types var = pybamm.standard_spatial_vars var_pts = {var.x_n: 2, var.x_s: 2, var.x_p: 2, var.y: 64, var.z: 64} submesh_types = { "negative electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "separator": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "positive electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "current collector": pybamm.MeshGenerator(pybamm.ScikitUniform2DSubMesh), } # set base parameters param = pybamm.ParameterValues( values={ "Electrode width [m]": 0.4, "Electrode height [m]": 0.5, "Negative tab width [m]": 0.1, "Negative tab centre y-coordinate [m]": 0.0, "Negative tab centre z-coordinate [m]": 0.25, "Positive tab centre y-coordinate [m]": 0.4, "Positive tab centre z-coordinate [m]": 0.25, "Positive tab width [m]": 0.1, "Negative electrode thickness [m]": 0.3, "Separator thickness [m]": 0.3, "Positive electrode thickness [m]": 0.3, }) # check mesh can be built geometry = pybamm.battery_geometry(include_particles=False, current_collector_dimension=2) param.process_geometry(geometry) pybamm.Mesh(geometry, submesh_types, var_pts)
def test_mesh_coord_sys(self): param = pybamm.ParameterValues( values={ "Negative electrode thickness [m]": 0.1, "Separator thickness [m]": 0.2, "Positive electrode thickness [m]": 0.3, }) geometry = pybamm.battery_geometry() param.process_geometry(geometry) var = pybamm.standard_spatial_vars var_pts = { var.x_n: 10, var.x_s: 10, var.x_p: 12, var.r_n: 5, var.r_p: 6 } submesh_types = { "negative electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "separator": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "positive electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "negative particle": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "positive particle": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "current collector": pybamm.MeshGenerator(pybamm.SubMesh0D), } # create mesh mesh = pybamm.Mesh(geometry, submesh_types, var_pts) for submesh in mesh.values(): if not isinstance(submesh, pybamm.SubMesh0D): self.assertTrue(submesh.coord_sys in pybamm.KNOWN_COORD_SYS)
def test_read_parameters(self): geo = pybamm.geometric_parameters L_n = geo.L_n L_s = geo.L_s L_p = geo.L_p L_y = geo.L_y L_z = geo.L_z tab_n_y = geo.Centre_y_tab_n tab_n_z = geo.Centre_z_tab_n L_tab_n = geo.L_tab_n tab_p_y = geo.Centre_y_tab_p tab_p_z = geo.Centre_z_tab_p L_tab_p = geo.L_tab_p geometry = pybamm.battery_geometry(current_collector_dimension=2) self.assertEqual( set([x.name for x in geometry.parameters]), set([ x.name for x in [ L_n, L_s, L_p, L_y, L_z, tab_n_y, tab_n_z, L_tab_n, tab_p_y, tab_p_z, L_tab_p, ] ]), ) self.assertTrue( all(isinstance(x, pybamm.Parameter) for x in geometry.parameters))
"positive interface current"] = pybamm.interface.CurrentForInverseButlerVolmer( model.param, "Positive", "lithium-ion main") model.submodels[ "electrolyte diffusion"] = pybamm.electrolyte_diffusion.ConstantConcentration( model.param) model.submodels[ "electrolyte conductivity"] = pybamm.electrolyte_conductivity.LeadingOrder( model.param) model.submodels["negative sei"] = pybamm.sei.NoSEI(model.param, "Negative") model.submodels["positive sei"] = pybamm.sei.NoSEI(model.param, "Positive") # build model model.build_model() # create geometry geometry = pybamm.battery_geometry() # process model and geometry param = model.default_parameter_values param.process_model(model) param.process_geometry(geometry) # set mesh # Note: li-ion base model has defaults for mesh and var_pts mesh = pybamm.Mesh(geometry, model.default_submesh_types, model.default_var_pts) # discretise model # Note: li-ion base model has default spatial methods disc = pybamm.Discretisation(mesh, model.default_spatial_methods) disc.process_model(model)
def default_geometry(self): return pybamm.battery_geometry( current_collector_dimension=self.options["dimensionality"] )
def default_geometry(self): return pybamm.battery_geometry( include_particles=False, current_collector_dimension=self.options["dimensionality"], )
def get_p2d_mesh_for_testing(xpts=None, rpts=10): geometry = pybamm.battery_geometry() return get_mesh_for_testing(xpts=xpts, rpts=rpts, geometry=geometry)
def test_geometry_error(self): with self.assertRaisesRegex(pybamm.GeometryError, "Invalid current"): pybamm.battery_geometry(current_collector_dimension=4)
def test_combine_submeshes(self): param = pybamm.ParameterValues( values={ "Negative electrode thickness [m]": 0.1, "Separator thickness [m]": 0.2, "Positive electrode thickness [m]": 0.3, }) geometry = pybamm.battery_geometry() param.process_geometry(geometry) # provide mesh properties var = pybamm.standard_spatial_vars var_pts = { var.x_n: 10, var.x_s: 10, var.x_p: 12, var.r_n: 5, var.r_p: 6 } submesh_types = { "negative electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "separator": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "positive electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "negative particle": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "positive particle": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "current collector": pybamm.MeshGenerator(pybamm.SubMesh0D), } # create mesh mesh = pybamm.Mesh(geometry, submesh_types, var_pts) # create submesh submesh = mesh.combine_submeshes("negative electrode", "separator") self.assertEqual(submesh.edges[0], 0) self.assertEqual(submesh.edges[-1], mesh["separator"].edges[-1]) np.testing.assert_almost_equal( submesh.nodes - np.concatenate( [mesh["negative electrode"].nodes, mesh["separator"].nodes]), 0, ) np.testing.assert_almost_equal(submesh.internal_boundaries, [0.1 / 0.6]) with self.assertRaises(pybamm.DomainError): mesh.combine_submeshes("negative electrode", "positive electrode") # test errors geometry = { "negative electrode": { var.x_n: { "min": 0, "max": 0.5 } }, "negative particle": { var.r_n: { "min": 0.5, "max": 1 } }, } param.process_geometry(geometry) mesh = pybamm.Mesh(geometry, submesh_types, var_pts) with self.assertRaisesRegex(pybamm.DomainError, "trying"): mesh.combine_submeshes("negative electrode", "negative particle") with self.assertRaisesRegex( ValueError, "Submesh domains being combined cannot be empty"): mesh.combine_submeshes()
def test_manufactured_solution_exponential_grid(self): param = pybamm.ParameterValues( values={ "Electrode width [m]": 1, "Electrode height [m]": 1, "Negative tab width [m]": 1, "Negative tab centre y-coordinate [m]": 0.5, "Negative tab centre z-coordinate [m]": 0, "Positive tab width [m]": 1, "Positive tab centre y-coordinate [m]": 0.5, "Positive tab centre z-coordinate [m]": 1, "Negative electrode thickness [m]": 0.3, "Separator thickness [m]": 0.3, "Positive electrode thickness [m]": 0.3, } ) geometry = pybamm.battery_geometry( include_particles=False, current_collector_dimension=2 ) param.process_geometry(geometry) var = pybamm.standard_spatial_vars var_pts = {var.x_n: 3, var.x_s: 3, var.x_p: 3, var.y: 32, var.z: 32} submesh_types = { "negative electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "separator": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "positive electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "current collector": pybamm.MeshGenerator( pybamm.ScikitExponential2DSubMesh ), } mesh = pybamm.Mesh(geometry, submesh_types, var_pts) spatial_methods = { "macroscale": pybamm.FiniteVolume(), "current collector": pybamm.ScikitFiniteElement(), } disc = pybamm.Discretisation(mesh, spatial_methods) # laplace of u = cos(pi*y)*sin(pi*z) var = pybamm.Variable("var", domain="current collector") laplace_eqn = pybamm.laplacian(var) # set boundary conditions ("negative tab" = bottom of unit square, # "positive tab" = top of unit square, elsewhere normal derivative is zero) disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Dirichlet"), "positive tab": (pybamm.Scalar(0), "Dirichlet"), } } disc.set_variable_slices([var]) laplace_eqn_disc = disc.process_symbol(laplace_eqn) y_vertices = mesh["current collector"].coordinates[0, :][:, np.newaxis] z_vertices = mesh["current collector"].coordinates[1, :][:, np.newaxis] u = np.cos(np.pi * y_vertices) * np.sin(np.pi * z_vertices) mass = pybamm.Mass(var) mass_disc = disc.process_symbol(mass) soln = -np.pi ** 2 * u np.testing.assert_array_almost_equal( laplace_eqn_disc.evaluate(None, u), mass_disc.entries @ soln, decimal=1 )