Example #1
0
def get_unit_2p1D_mesh_for_testing(ypts=15, zpts=15):
    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.Geometryxp1DMacro(cc_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: ypts, var.z: zpts}

    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),
    }

    return pybamm.Mesh(geometry, submesh_types, var_pts)
    def test_mesh_creation(self):
        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.1,
                "Negative tab centre z-coordinate [m]": 0.5,
                "Positive tab width [m]": 0.1,
                "Positive tab centre y-coordinate [m]": 0.3,
                "Positive tab centre z-coordinate [m]": 0.5,
                "Negative electrode thickness [m]": 0.3,
                "Separator thickness [m]": 0.3,
                "Positive electrode thickness [m]": 0.3,
            })

        geometry = pybamm.Geometryxp1DMacro(cc_dimension=2)
        param.process_geometry(geometry)

        var = pybamm.standard_spatial_vars
        var_pts = {var.x_n: 10, var.x_s: 7, var.x_p: 12, var.y: 16, var.z: 24}

        y_edges = np.linspace(0, 0.8, 16)
        z_edges = np.linspace(0, 1, 24)

        submesh_params = {"y_edges": y_edges, "z_edges": z_edges}
        submesh_types = {
            "negative electrode":
            pybamm.MeshGenerator(pybamm.Uniform1DSubMesh),
            "separator":
            pybamm.MeshGenerator(pybamm.Uniform1DSubMesh),
            "positive electrode":
            pybamm.MeshGenerator(pybamm.Uniform1DSubMesh),
            "current collector":
            pybamm.MeshGenerator(pybamm.UserSupplied2DSubMesh, submesh_params),
        }

        mesh_type = pybamm.Mesh

        # create mesh
        mesh = mesh_type(geometry, submesh_types, var_pts)

        # check boundary locations
        self.assertEqual(mesh["negative electrode"][0].edges[0], 0)
        self.assertEqual(mesh["positive electrode"][0].edges[-1], 1)

        # check internal boundary locations
        self.assertEqual(mesh["negative electrode"][0].edges[-1],
                         mesh["separator"][0].edges[0])
        self.assertEqual(mesh["positive electrode"][0].edges[0],
                         mesh["separator"][0].edges[-1])
        for domain in mesh:
            if domain == "current collector":
                # NOTE: only for degree 1
                npts = var_pts[var.y] * var_pts[var.z]
                self.assertEqual(mesh[domain][0].npts, npts)
            else:
                self.assertEqual(len(mesh[domain][0].edges),
                                 len(mesh[domain][0].nodes) + 1)
    def test_init_failure(self):
        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),
        }
        geometry = pybamm.Geometryxp1DMacro(cc_dimension=2)
        with self.assertRaises(KeyError):
            pybamm.Mesh(geometry, submesh_types, {})

        var = pybamm.standard_spatial_vars
        var_pts = {var.x_n: 10, var.x_s: 10, var.x_p: 10, var.y: 10, var.z: 10}
        # there are parameters in the variables that need to be processed
        with self.assertRaises(NotImplementedError):
            pybamm.Mesh(geometry, submesh_types, var_pts)

        lims = {var.x_n: {"min": pybamm.Scalar(0), "max": pybamm.Scalar(1)}}
        with self.assertRaises(pybamm.GeometryError):
            pybamm.ScikitUniform2DSubMesh(lims, None, None)

        lims = {
            var.x_n: {
                "min": pybamm.Scalar(0),
                "max": pybamm.Scalar(1)
            },
            var.x_p: {
                "min": pybamm.Scalar(0),
                "max": pybamm.Scalar(1)
            },
        }
        with self.assertRaises(pybamm.DomainError):
            pybamm.ScikitUniform2DSubMesh(lims, None, None)

        lims = {
            var.y: {
                "min": pybamm.Scalar(0),
                "max": pybamm.Scalar(1)
            },
            var.z: {
                "min": pybamm.Scalar(0),
                "max": pybamm.Scalar(1)
            },
        }
        npts = {var.y.id: 10, var.z.id: 10}
        var.z.coord_sys = "not cartesian"
        with self.assertRaises(pybamm.DomainError):
            pybamm.ScikitUniform2DSubMesh(lims, npts, None)
        var.z.coord_sys = "cartesian"
Example #4
0
 def test_geometry_keys(self):
     geometry = pybamm.Geometryxp1DMacro(cc_dimension=1)
     for key, prim_sec_vars in geometry.items():
         self.assertIn("primary", prim_sec_vars.keys())
         if key != "current collector":
             self.assertIn("secondary", prim_sec_vars.keys())
             var = pybamm.standard_spatial_vars
             self.assertEqual(
                 list(prim_sec_vars["secondary"].keys())[0].id, var.z.id)
         for spatial_vars in prim_sec_vars.values():
             all(
                 self.assertIsInstance(spatial_var, pybamm.SpatialVariable)
                 for spatial_var in spatial_vars.keys()
                 if spatial_var not in ["negative", "positive"])
Example #5
0
    def test_geometry_keys(self):
        geometry = pybamm.Geometryxp1DMacro(cc_dimension=2)
        for key, prim_sec_vars in geometry.items():
            self.assertIn("primary", prim_sec_vars.keys())
            if key != "current collector":
                self.assertIn("secondary", prim_sec_vars.keys())
                var = pybamm.standard_spatial_vars
                self.assertIn(var.y, prim_sec_vars["secondary"].keys())
                self.assertIn(var.z, prim_sec_vars["secondary"].keys())

            for spatial_vars in prim_sec_vars.values():
                all(
                    self.assertIsInstance(spatial_var, pybamm.SpatialVariable)
                    for spatial_var in spatial_vars.keys()
                    if spatial_var not in ["negative", "positive"])

        def test_init_failure(self):
            with self.assertRaises(pybamm.GeometryError):
                pybamm.Geometryxp1DMacro(cc_dimension=3)
Example #6
0
    def test_1plus1D_tabs_right_left(self):
        param = pybamm.ParameterValues(
            values={
                "Electrode width [m]": 0.4,
                "Electrode height [m]": 0.5,
                "Negative tab centre z-coordinate [m]": 0.5,
                "Positive tab centre z-coordinate [m]": 0.0,
                "Negative electrode thickness [m]": 0.3,
                "Separator thickness [m]": 0.3,
                "Positive electrode thickness [m]": 0.3,
            })

        geometry = pybamm.Geometryxp1DMacro(cc_dimension=1)
        param.process_geometry(geometry)

        var = pybamm.standard_spatial_vars
        var_pts = {var.x_n: 10, var.x_s: 7, var.x_p: 12, var.z: 24}

        submesh_types = {
            "negative electrode":
            pybamm.MeshGenerator(pybamm.Uniform1DSubMesh),
            "separator": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh),
            "positive electrode":
            pybamm.MeshGenerator(pybamm.Uniform1DSubMesh),
            "current collector": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh),
        }

        mesh_type = pybamm.Mesh

        # create mesh
        mesh = mesh_type(geometry, submesh_types, var_pts)

        # negative tab should be "right"
        self.assertEqual(mesh["current collector"][0].tabs["negative tab"],
                         "right")

        # positive tab should be "left"
        self.assertEqual(mesh["current collector"][0].tabs["positive tab"],
                         "left")
    def test_tab_error(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),
        }

        mesh_type = pybamm.Mesh

        # 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.1,
                "Negative tab centre z-coordinate [m]": 0.5,
                "Positive tab centre y-coordinate [m]": 10,
                "Positive tab centre z-coordinate [m]": 10,
                "Positive tab width [m]": 0.1,
                "Negative electrode thickness [m]": 0.3,
                "Separator thickness [m]": 0.3,
                "Positive electrode thickness [m]": 0.3,
            })

        # check error raised if tab not on boundary
        geometry = pybamm.Geometryxp1DMacro(cc_dimension=2)
        param.process_geometry(geometry)
        with self.assertRaises(pybamm.GeometryError):
            mesh_type(geometry, submesh_types, var_pts)
Example #8
0
 def test_init_failure(self):
     with self.assertRaises(pybamm.GeometryError):
         pybamm.Geometryxp1DMacro(cc_dimension=3)
    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.Geometryxp1DMacro(cc_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"][0].coordinates[0, :][:,
                                                                    np.newaxis]
        z_vertices = mesh["current collector"][0].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)