Exemple #1
0
 def _current_collector_heating(self, variables):
     "Compute Ohmic heating in current collectors"
     # TODO: implement grad in 0D to return a scalar zero
     # TODO: implement grad_squared in other spatial methods so that the if
     # statement can be removed
     # In the limit of infinitely large current collector conductivity (i.e.
     # 0D current collectors), the Ohmic heating in the current collectors is
     # zero
     if self.cc_dimension == 0:
         Q_s_cn = pybamm.Scalar(0)
         Q_s_cp = pybamm.Scalar(0)
     # Otherwise we compute the Ohmic heating for 1 or 2D current collectors
     elif self.cc_dimension in [1, 2]:
         phi_s_cn = variables["Negative current collector potential"]
         phi_s_cp = variables["Positive current collector potential"]
         if self.cc_dimension == 1:
             Q_s_cn = self.param.sigma_cn_prime * pybamm.inner(
                 pybamm.grad(phi_s_cn), pybamm.grad(phi_s_cn))
             Q_s_cp = self.param.sigma_cp_prime * pybamm.inner(
                 pybamm.grad(phi_s_cp), pybamm.grad(phi_s_cp))
         elif self.cc_dimension == 2:
             # Inner not implemented in 2D -- have to call grad_squared directly
             Q_s_cn = self.param.sigma_cn_prime * pybamm.grad_squared(
                 phi_s_cn)
             Q_s_cp = self.param.sigma_cp_prime * pybamm.grad_squared(
                 phi_s_cp)
     return Q_s_cn, Q_s_cp
    def _current_collector_heating(self, variables):
        """Returns the heat source terms in the 2D current collector"""
        phi_s_cn = variables["Negative current collector potential"]
        phi_s_cp = variables["Positive current collector potential"]

        Q_s_cn = self.param.sigma_cn_prime * pybamm.grad_squared(phi_s_cn)
        Q_s_cp = self.param.sigma_cp_prime * pybamm.grad_squared(phi_s_cp)
        return Q_s_cn, Q_s_cp
Exemple #3
0
 def _current_collector_heating(self, variables):
     """Returns the heat source terms in the 2D current collector"""
     phi_s_cn = variables["Negative current collector potential"]
     phi_s_cp = variables["Positive current collector potential"]
     # Note: grad not implemented in 2D weak form, but can compute grad squared
     # directly
     Q_s_cn = self.param.sigma_cn_prime * pybamm.grad_squared(phi_s_cn)
     Q_s_cp = self.param.sigma_cp_prime * pybamm.grad_squared(phi_s_cp)
     return Q_s_cn, Q_s_cp
    def test_gradient(self):
        mesh = get_unit_2p1D_mesh_for_testing(ypts=32, zpts=32, include_particles=False)
        spatial_methods = {
            "macroscale": pybamm.FiniteVolume(),
            "current collector": pybamm.ScikitFiniteElement(),
        }
        disc = pybamm.Discretisation(mesh, spatial_methods)

        # test gradient of 5*y + 6*z
        var = pybamm.Variable("var", domain="current collector")
        disc.set_variable_slices([var])

        y = mesh["current collector"].coordinates[0, :]
        z = mesh["current collector"].coordinates[1, :]

        gradient = pybamm.grad(var)
        grad_disc = disc.process_symbol(gradient)
        grad_disc_y, grad_disc_z = grad_disc.children

        np.testing.assert_array_almost_equal(
            grad_disc_y.evaluate(None, 5 * y + 6 * z),
            5 * np.ones_like(y)[:, np.newaxis],
        )
        np.testing.assert_array_almost_equal(
            grad_disc_z.evaluate(None, 5 * y + 6 * z),
            6 * np.ones_like(z)[:, np.newaxis],
        )

        # check grad_squared positive
        eqn = pybamm.grad_squared(var)
        eqn_disc = disc.process_symbol(eqn)
        ans = eqn_disc.evaluate(None, 3 * y ** 2)
        np.testing.assert_array_less(0, ans)
Exemple #5
0
    def test_discretise_equations(self):
        # get mesh
        mesh = get_2p1d_mesh_for_testing()
        spatial_methods = {
            "macroscale": pybamm.FiniteVolume,
            "current collector": pybamm.ScikitFiniteElement,
        }
        disc = pybamm.Discretisation(mesh, spatial_methods)
        # discretise some equations
        var = pybamm.Variable("var", domain="current collector")
        y = pybamm.SpatialVariable("y", ["current collector"])
        z = pybamm.SpatialVariable("z", ["current collector"])
        disc.set_variable_slices([var])
        y_test = np.ones(mesh["current collector"][0].npts)
        unit_source = pybamm.Broadcast(1, "current collector")
        disc.bcs = {
            var.id: {
                "negative tab": (pybamm.Scalar(0), "Neumann"),
                "positive tab": (pybamm.Scalar(0), "Neumann"),
            }
        }

        for eqn in [
                pybamm.laplacian(var),
                pybamm.source(unit_source, var),
                pybamm.laplacian(var) - pybamm.source(unit_source, var),
                pybamm.source(var, var),
                pybamm.laplacian(var) - pybamm.source(2 * var, var),
                pybamm.laplacian(var) -
                pybamm.source(unit_source**2 + 1 / var, var),
                pybamm.Integral(var, [y, z]) - 1,
                pybamm.source(var, var, boundary=True),
                pybamm.laplacian(var) -
                pybamm.source(unit_source, var, boundary=True),
                pybamm.laplacian(var) -
                pybamm.source(unit_source**2 + 1 / var, var, boundary=True),
                pybamm.grad_squared(var),
        ]:
            # Check that equation can be evaluated in each case
            # Dirichlet
            disc.bcs = {
                var.id: {
                    "negative tab": (pybamm.Scalar(0), "Dirichlet"),
                    "positive tab": (pybamm.Scalar(1), "Dirichlet"),
                }
            }
            eqn_disc = disc.process_symbol(eqn)
            eqn_disc.evaluate(None, y_test)
            # Neumann
            disc.bcs = {
                var.id: {
                    "negative tab": (pybamm.Scalar(0), "Neumann"),
                    "positive tab": (pybamm.Scalar(1), "Neumann"),
                }
            }
            eqn_disc = disc.process_symbol(eqn)
            eqn_disc.evaluate(None, y_test)
            # One of each
            disc.bcs = {
                var.id: {
                    "negative tab": (pybamm.Scalar(0), "Neumann"),
                    "positive tab": (pybamm.Scalar(1), "Dirichlet"),
                }
            }
            eqn_disc = disc.process_symbol(eqn)
            eqn_disc.evaluate(None, y_test)
            # One of each
            disc.bcs = {
                var.id: {
                    "negative tab": (pybamm.Scalar(0), "Dirichlet"),
                    "positive tab": (pybamm.Scalar(1), "Neumann"),
                }
            }
            eqn_disc = disc.process_symbol(eqn)
            eqn_disc.evaluate(None, y_test)

        # check  ValueError raised for non Dirichlet or Neumann BCs
        eqn = pybamm.laplacian(var) - pybamm.source(unit_source, var)
        disc.bcs = {
            var.id: {
                "negative tab": (pybamm.Scalar(0), "Dirichlet"),
                "positive tab": (pybamm.Scalar(1), "Other BC"),
            }
        }
        with self.assertRaises(ValueError):
            eqn_disc = disc.process_symbol(eqn)
        disc.bcs = {
            var.id: {
                "negative tab": (pybamm.Scalar(0), "Other BC"),
                "positive tab": (pybamm.Scalar(1), "Neumann"),
            }
        }
        with self.assertRaises(ValueError):
            eqn_disc = disc.process_symbol(eqn)

        # raise ModelError if no BCs provided
        new_var = pybamm.Variable("new_var", domain="current collector")
        disc.set_variable_slices([new_var])
        eqn = pybamm.laplacian(new_var)
        with self.assertRaises(pybamm.ModelError):
            eqn_disc = disc.process_symbol(eqn)

        # check GeometryError if using scikit-fem not in y or z
        x = pybamm.SpatialVariable("x", ["current collector"])
        with self.assertRaises(pybamm.GeometryError):
            disc.process_symbol(x)