Esempio n. 1
0
    def test_div(self):
        # divergence of scalar symbol should fail
        a = pybamm.Symbol("a")
        with self.assertRaisesRegex(
                pybamm.DomainError,
                "Cannot take divergence of 'a' since its domain is empty",
        ):
            pybamm.Divergence(a)

        # divergence of variable evaluating on edges should fail
        a = pybamm.PrimaryBroadcast(pybamm.Scalar(1), "test")
        with self.assertRaisesRegex(TypeError, "evaluate on edges"):
            pybamm.Divergence(a)

        # divergence of broadcast should return broadcasted zero
        a = pybamm.PrimaryBroadcastToEdges(pybamm.Variable("a"), "test domain")
        div = pybamm.div(a)
        self.assertIsInstance(div, pybamm.PrimaryBroadcast)
        self.assertIsInstance(div.child, pybamm.PrimaryBroadcast)
        self.assertIsInstance(div.child.child, pybamm.Scalar)
        self.assertEqual(div.child.child.value, 0)

        # otherwise divergence should work
        a = pybamm.Symbol("a", domain="test domain")
        div = pybamm.Divergence(pybamm.Gradient(a))
        self.assertEqual(div.domain, a.domain)

        # check div commutes with negation
        a = pybamm.Symbol("a", domain="test domain")
        div = pybamm.div(-pybamm.Gradient(a))
        self.assertEqual(div.id, (-pybamm.Divergence(pybamm.Gradient(a))).id)
Esempio n. 2
0
    def get_fundamental_variables(self):

        # Electrolyte pressure
        p_n = pybamm.Variable(
            "Negative electrode pressure",
            domain="negative electrode",
            auxiliary_domains={"secondary": "current collector"},
        )
        p_p = pybamm.Variable(
            "Positive electrode pressure",
            domain="positive electrode",
            auxiliary_domains={"secondary": "current collector"},
        )
        variables = self._get_standard_neg_pos_pressure_variables(p_n, p_p)

        # TODO: add permeability and viscosity, and other terms
        v_mass_n = -pybamm.grad(p_n)
        v_mass_p = -pybamm.grad(p_p)
        v_box_n = v_mass_n
        v_box_p = v_mass_p
        variables.update(
            self._get_standard_neg_pos_velocity_variables(v_box_n, v_box_p))

        div_v_box_n = pybamm.div(v_box_n)
        div_v_box_p = pybamm.div(v_box_p)
        variables.update(
            self._get_standard_neg_pos_acceleration_variables(
                div_v_box_n, div_v_box_p))

        return variables
Esempio n. 3
0
    def test_exceptions(self):
        c_n = pybamm.Variable("c", domain=["negative electrode"])
        N_n = pybamm.grad(c_n)
        c_s = pybamm.Variable("c", domain=["separator"])
        N_s = pybamm.grad(c_s)
        model = pybamm.BaseModel()
        model.rhs = {c_n: pybamm.div(N_n), c_s: pybamm.div(N_s)}
        model.initial_conditions = {c_n: pybamm.Scalar(3), c_s: pybamm.Scalar(1)}
        model.boundary_conditions = {
            c_n: {"left": (0, "Neumann"), "right": (0, "Neumann")},
            c_s: {"left": (0, "Neumann"), "right": (0, "Neumann")},
        }

        disc = get_discretisation_for_testing()

        # check raises error if different sized key and output var
        model.variables = {c_n.name: c_s}
        with self.assertRaisesRegex(pybamm.ModelError, "variable and its eqn"):
            disc.process_model(model)

        # check doesn't raise if concatenation
        model.variables = {c_n.name: pybamm.Concatenation(c_n, c_s)}
        disc.process_model(model, inplace=False)

        # check doesn't raise if broadcast
        model.variables = {
            c_n.name: pybamm.PrimaryBroadcast(
                pybamm.InputParameter("a"), ["negative electrode"]
            )
        }
        disc.process_model(model)
Esempio n. 4
0
    def set_rhs(self, variables):

        c, N, _ = self._unpack(variables)

        if self.domain == "Negative":
            self.rhs = {c: -(1 / self.param.C_n) * pybamm.div(N)}

        elif self.domain == "Positive":
            self.rhs = {c: -(1 / self.param.C_p) * pybamm.div(N)}
Esempio n. 5
0
    def set_rhs(self, variables):
        c_s = variables[self.domain + " particle concentration"]
        N_s = variables[self.domain + " particle flux"]
        R = variables[self.domain + " particle radius"]

        if self.domain == "Negative":
            self.rhs = {c_s: -(1 / (R**2 * self.param.C_n)) * pybamm.div(N_s)}

        elif self.domain == "Positive":
            self.rhs = {c_s: -(1 / (R**2 * self.param.C_p)) * pybamm.div(N_s)}
Esempio n. 6
0
    def set_rhs(self, variables):
        c_s_xav = variables["X-averaged " + self.domain.lower() +
                            " particle concentration"]
        N_s_xav = variables["X-averaged " + self.domain.lower() +
                            " particle flux"]

        if self.domain == "Negative":
            self.rhs = {c_s_xav: -(1 / self.param.C_n) * pybamm.div(N_s_xav)}

        elif self.domain == "Positive":
            self.rhs = {c_s_xav: -(1 / self.param.C_p) * pybamm.div(N_s_xav)}
Esempio n. 7
0
 def test_has_spatial_derivatives(self):
     var = pybamm.Variable("var", domain="test")
     grad_eqn = pybamm.grad(var)
     div_eqn = pybamm.div(pybamm.standard_spatial_vars.x_edge)
     grad_div_eqn = pybamm.div(grad_eqn)
     algebraic_eqn = 2 * var + 3
     self.assertTrue(grad_eqn.has_symbol_of_classes(pybamm.Gradient))
     self.assertFalse(grad_eqn.has_symbol_of_classes(pybamm.Divergence))
     self.assertFalse(div_eqn.has_symbol_of_classes(pybamm.Gradient))
     self.assertTrue(div_eqn.has_symbol_of_classes(pybamm.Divergence))
     self.assertTrue(grad_div_eqn.has_symbol_of_classes(pybamm.Gradient))
     self.assertTrue(grad_div_eqn.has_symbol_of_classes(pybamm.Divergence))
     self.assertFalse(algebraic_eqn.has_symbol_of_classes(pybamm.Gradient))
     self.assertFalse(algebraic_eqn.has_symbol_of_classes(pybamm.Divergence))
Esempio n. 8
0
    def set_algebraic(self, variables):
        p_n = variables["Negative electrode pressure"]
        p_p = variables["Positive electrode pressure"]

        j_n = variables["Negative electrode interfacial current density"]
        j_p = variables["Positive electrode interfacial current density"]

        v_box_n = variables["Negative electrode volume-averaged velocity"]
        v_box_p = variables["Positive electrode volume-averaged velocity"]

        # Problems in the x-direction for p_n and p_p
        self.algebraic = {
            p_n: pybamm.div(v_box_n) - self.param.beta_n * j_n,
            p_p: pybamm.div(v_box_p) - self.param.beta_p * j_p,
        }
Esempio n. 9
0
    def test_check_well_posedness_initial_boundary_conditions(self):
        # Well-posed model - Dirichlet
        whole_cell = ["negative electrode", "separator", "positive electrode"]
        model = pybamm.BaseModel()
        c = pybamm.Variable("c", domain=whole_cell)
        model.rhs = {c: 5 * pybamm.div(pybamm.grad(c)) - 1}
        model.initial_conditions = {c: 1}
        model.boundary_conditions = {
            c: {
                "left": (0, "Dirichlet"),
                "right": (0, "Dirichlet")
            }
        }
        model.check_well_posedness()

        # Well-posed model - Neumann
        model.boundary_conditions = {
            c: {
                "left": (0, "Neumann"),
                "right": (0, "Neumann")
            }
        }
        model.check_well_posedness()

        # Model with bad initial conditions (expect assertion error)
        d = pybamm.Variable("d", domain=whole_cell)
        model.initial_conditions = {d: 3}
        with self.assertRaisesRegex(pybamm.ModelError, "initial condition"):
            model.check_well_posedness()

        # Algebraic well-posed model
        whole_cell = ["negative electrode", "separator", "positive electrode"]
        model = pybamm.BaseModel()
        model.algebraic = {c: 5 * pybamm.div(pybamm.grad(c)) - 1}
        model.boundary_conditions = {
            c: {
                "left": (0, "Dirichlet"),
                "right": (0, "Dirichlet")
            }
        }
        model.check_well_posedness()
        model.boundary_conditions = {
            c: {
                "left": (0, "Neumann"),
                "right": (0, "Neumann")
            }
        }
        model.check_well_posedness()
Esempio n. 10
0
    def test_process_model_not_inplace(self):
        # concatenation of variables as the key
        c = pybamm.Variable("c", domain=["negative electrode"])
        N = pybamm.grad(c)
        model = pybamm.BaseModel()
        model.rhs = {c: pybamm.div(N)}
        model.initial_conditions = {c: pybamm.Scalar(3)}
        model.boundary_conditions = {
            c: {"left": (0, "Neumann"), "right": (0, "Neumann")}
        }
        model.check_well_posedness()

        # create discretisation
        disc = get_discretisation_for_testing()
        mesh = disc.mesh
        submesh = mesh["negative electrode"]

        discretised_model = disc.process_model(model, inplace=False)
        y0 = discretised_model.concatenated_initial_conditions.evaluate()
        np.testing.assert_array_equal(
            y0, 3 * np.ones_like(submesh.nodes[:, np.newaxis])
        )

        # grad and div are identity operators here
        np.testing.assert_array_equal(
            y0, discretised_model.concatenated_rhs.evaluate(None, y0)
        )
        discretised_model.check_well_posedness()
Esempio n. 11
0
    def test_mass_matrix_shape(self):
        """
        Test mass matrix shape
        """
        # one equation
        whole_cell = ["negative electrode", "separator", "positive electrode"]
        c = pybamm.Variable("c", domain=whole_cell)
        N = pybamm.grad(c)
        model = pybamm.BaseModel()
        model.rhs = {c: pybamm.div(N)}
        model.initial_conditions = {c: pybamm.Scalar(0)}
        model.boundary_conditions = {
            c: {
                "left": (0, "Dirichlet"),
                "right": (0, "Dirichlet")
            }
        }
        model.variables = {"c": c, "N": N}

        # create discretisation
        mesh = get_mesh_for_testing()
        spatial_methods = {"macroscale": pybamm.FiniteVolume()}
        disc = pybamm.Discretisation(mesh, spatial_methods)

        combined_submesh = mesh.combine_submeshes(*whole_cell)
        disc.process_model(model)

        # mass matrix
        mass = np.eye(combined_submesh[0].npts)
        np.testing.assert_array_equal(mass,
                                      model.mass_matrix.entries.toarray())
Esempio n. 12
0
    def set_rhs(self, variables):
        "Composite reaction-diffusion with source terms from leading order"

        param = self.param

        eps_0 = separator_and_positive_only(variables["Leading-order porosity"])
        deps_0_dt = separator_and_positive_only(
            variables["Leading-order porosity change"]
        )
        c_ox = variables["Separator and positive electrode oxygen concentration"]
        N_ox = variables["Oxygen flux"].orphans[1]

        if self.extended is False:
            pos_reactions = sum(
                reaction["Positive"]["s_ox"]
                * variables["Leading-order " + reaction["Positive"]["aj"].lower()]
                for reaction in self.reactions.values()
            )
        else:
            pos_reactions = sum(
                reaction["Positive"]["s_ox"] * variables[reaction["Positive"]["aj"]]
                for reaction in self.reactions.values()
            )
        sep_reactions = pybamm.FullBroadcast(0, "separator", "current collector")
        source_terms_0 = (
            pybamm.Concatenation(sep_reactions, pos_reactions) / param.gamma_e
        )

        self.rhs = {
            c_ox: (1 / eps_0)
            * (-pybamm.div(N_ox) / param.C_e + source_terms_0 - c_ox * deps_0_dt)
        }
Esempio n. 13
0
    def test_p2d_mass_matrix_shape(self):
        """
        Test mass matrix shape in the pseudo 2-dimensional case
        """
        c = pybamm.Variable("c", domain=["negative particle"])
        N = pybamm.grad(c)
        model = pybamm.BaseModel()
        model.rhs = {c: pybamm.div(N)}
        model.initial_conditions = {c: pybamm.Scalar(0)}
        model.boundary_conditions = {
            c: {
                "left": (0, "Dirichlet"),
                "right": (0, "Dirichlet")
            }
        }
        model.variables = {"c": c, "N": N}
        mesh = get_p2d_mesh_for_testing()
        spatial_methods = {"negative particle": pybamm.FiniteVolume()}
        disc = pybamm.Discretisation(mesh, spatial_methods)
        disc.process_model(model)

        prim_pts = mesh["negative particle"][0].npts
        sec_pts = len(mesh["negative particle"])
        mass_local = eye(prim_pts)
        mass = kron(eye(sec_pts), mass_local)
        np.testing.assert_array_equal(mass.toarray(),
                                      model.mass_matrix.entries.toarray())
Esempio n. 14
0
    def set_rhs(self, variables):
        "Composite reaction-diffusion with source terms from leading order"

        param = self.param

        eps_0 = variables["Leading-order porosity"]
        deps_0_dt = variables["Leading-order porosity change"]
        c_e = variables["Electrolyte concentration"]
        N_e = variables["Electrolyte flux"]
        if self.extended is False:
            sum_s_j = variables[
                "Leading-order sum of electrolyte reaction source terms"
            ]
        elif self.extended == "distributed":
            sum_s_j = variables["Sum of electrolyte reaction source terms"]
        elif self.extended == "average":
            sum_s_j_n_av = variables[
                "Sum of x-averaged negative electrode electrolyte reaction source terms"
            ]
            sum_s_j_p_av = variables[
                "Sum of x-averaged positive electrode electrolyte reaction source terms"
            ]
            sum_s_j = pybamm.Concatenation(
                pybamm.PrimaryBroadcast(sum_s_j_n_av, "negative electrode"),
                pybamm.FullBroadcast(0, "separator", "current collector"),
                pybamm.PrimaryBroadcast(sum_s_j_p_av, "positive electrode"),
            )
        source_terms = sum_s_j / self.param.gamma_e

        self.rhs = {
            c_e: (1 / eps_0)
            * (-pybamm.div(N_e) / param.C_e + source_terms - c_e * deps_0_dt)
        }
Esempio n. 15
0
    def test_grad_div_broadcast(self):
        # create mesh and discretisation
        spatial_methods = {"macroscale": pybamm.FiniteVolume()}
        mesh = get_mesh_for_testing()
        disc = pybamm.Discretisation(mesh, spatial_methods)

        a = pybamm.PrimaryBroadcast(1, "negative electrode")
        grad_a = disc.process_symbol(pybamm.grad(a))
        np.testing.assert_array_equal(grad_a.evaluate(), 0)

        a_edge = pybamm.PrimaryBroadcastToEdges(1, "negative electrode")
        div_a = disc.process_symbol(pybamm.div(a_edge))
        np.testing.assert_array_equal(div_a.evaluate(), 0)

        div_grad_a = disc.process_symbol(pybamm.div(pybamm.grad(a)))
        np.testing.assert_array_equal(div_grad_a.evaluate(), 0)
Esempio n. 16
0
    def test_new_copy(self):
        model = pybamm.BaseModel(name="a model")
        whole_cell = ["negative electrode", "separator", "positive electrode"]
        c = pybamm.Variable("c", domain=whole_cell)
        d = pybamm.Variable("d", domain=whole_cell)
        model.rhs = {c: 5 * pybamm.div(pybamm.grad(d)) - 1, d: -c}
        model.initial_conditions = {c: 1, d: 2}
        model.boundary_conditions = {
            c: {
                "left": (0, "Dirichlet"),
                "right": (0, "Dirichlet")
            },
            d: {
                "left": (0, "Dirichlet"),
                "right": (0, "Dirichlet")
            },
        }
        model.use_jacobian = False
        model.use_simplify = False
        model.convert_to_format = "python"

        new_model = model.new_copy()
        self.assertEqual(new_model.name, model.name)
        self.assertEqual(new_model.use_jacobian, model.use_jacobian)
        self.assertEqual(new_model.use_simplify, model.use_simplify)
        self.assertEqual(new_model.convert_to_format, model.convert_to_format)
        self.assertEqual(new_model.timescale, model.timescale)
Esempio n. 17
0
    def set_rhs(self, variables):

        param = self.param

        eps = variables["Porosity"]
        deps_dt = variables["Porosity change"]
        c_e = variables["Electrolyte concentration"]
        N_e = variables["Electrolyte flux"]
        # i_e = variables["Electrolyte current density"]

        # source_term = ((param.s - param.t_plus) / param.gamma_e) * pybamm.div(i_e)
        # source_term = pybamm.div(i_e) / param.gamma_e  # lithium-ion
        source_terms = sum(
            pybamm.Concatenation(
                reaction["Negative"]["s"] *
                variables[reaction["Negative"]["aj"]],
                pybamm.FullBroadcast(0, "separator", "current collector"),
                reaction["Positive"]["s"] *
                variables[reaction["Positive"]["aj"]],
            ) / param.gamma_e for reaction in self.reactions.values())

        self.rhs = {
            c_e: (1 / eps) *
            (-pybamm.div(N_e) / param.C_e + source_terms - c_e * deps_dt)
        }
    def set_rhs(self, variables):
        "Composite reaction-diffusion with source terms from leading order"

        param = self.param

        eps_0 = separator_and_positive_only(
            variables["Leading-order porosity"])
        deps_0_dt = separator_and_positive_only(
            variables["Leading-order porosity change"])
        c_ox = variables[
            "Separator and positive electrode oxygen concentration"]
        N_ox = variables["Oxygen flux"].orphans[1]

        if self.extended is False:
            j_ox_0 = variables[
                "Leading-order positive electrode oxygen interfacial current density"]
            pos_reactions = param.s_ox_Ox * j_ox_0
        else:
            j_ox_0 = variables[
                "Positive electrode oxygen interfacial current density"]
            pos_reactions = param.s_ox_Ox * j_ox_0
        sep_reactions = pybamm.FullBroadcast(0, "separator",
                                             "current collector")
        source_terms_0 = (pybamm.Concatenation(sep_reactions, pos_reactions) /
                          param.gamma_e)

        self.rhs = {
            c_ox: (1 / eps_0) *
            (-pybamm.div(N_ox) / param.C_e + source_terms_0 - c_ox * deps_0_dt)
        }
Esempio n. 19
0
    def set_rhs(self, variables):
        T = variables["Cell temperature"]
        T_n = variables["Negative electrode temperature"]
        T_s = variables["Separator temperature"]
        T_p = variables["Positive electrode temperature"]

        Q = variables["Total heating"]

        # Define volumetric heat capacity
        rho_k = pybamm.concatenation(
            self.param.rho_n(T_n),
            self.param.rho_s(T_s),
            self.param.rho_p(T_p),
        )

        # Devine thermal conductivity
        lambda_k = pybamm.concatenation(
            self.param.lambda_n(T_n),
            self.param.lambda_s(T_s),
            self.param.lambda_p(T_p),
        )

        # Fourier's law for heat flux
        q = -lambda_k * pybamm.grad(T)

        # N.B only y-z surface cooling is implemented for this model
        self.rhs = {
            T: (-pybamm.div(q) / self.param.delta**2 + self.param.B * Q) /
            (self.param.C_th * rho_k)
        }
Esempio n. 20
0
    def test_adding_1D_external_variable(self):
        model = pybamm.BaseModel()

        a = pybamm.Variable("a", domain=["test"])
        b = pybamm.Variable("b", domain=["test"])

        model.rhs = {a: a * b}
        model.boundary_conditions = {
            a: {
                "left": (0, "Dirichlet"),
                "right": (0, "Dirichlet")
            }
        }
        model.initial_conditions = {a: 0}
        model.external_variables = [b]
        model.variables = {
            "a": a,
            "b": b,
            "c": a * b,
            "grad b": pybamm.grad(b),
            "div grad b": pybamm.div(pybamm.grad(b)),
        }

        x = pybamm.SpatialVariable("x", domain="test", coord_sys="cartesian")
        geometry = {
            "test": {
                "primary": {
                    x: {
                        "min": pybamm.Scalar(0),
                        "max": pybamm.Scalar(1)
                    }
                }
            }
        }

        submesh_types = {"test": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh)}
        var_pts = {x: 10}
        mesh = pybamm.Mesh(geometry, submesh_types, var_pts)

        spatial_methods = {"test": pybamm.FiniteVolume()}
        disc = pybamm.Discretisation(mesh, spatial_methods)
        disc.process_model(model)

        self.assertEqual(disc.y_slices[a.id][0], slice(0, 10, None))

        self.assertEqual(model.y_slices[a][0], slice(0, 10, None))

        b_test = np.ones((10, 1))
        np.testing.assert_array_equal(
            model.variables["b"].evaluate(inputs={"b": b_test}), b_test)

        # check that b is added to the boundary conditions
        model.bcs[b.id]["left"]
        model.bcs[b.id]["right"]

        # check that grad and div(grad ) produce the correct shapes
        self.assertEqual(model.variables["b"].shape_for_testing, (10, 1))
        self.assertEqual(model.variables["grad b"].shape_for_testing, (11, 1))
        self.assertEqual(model.variables["div grad b"].shape_for_testing,
                         (10, 1))
Esempio n. 21
0
    def set_rhs(self, variables):

        param = self.param

        eps_s = variables["Separator porosity"]
        eps_p = variables["Positive electrode porosity"]
        eps = pybamm.concatenation(eps_s, eps_p)

        deps_dt_s = variables["Separator porosity change"]
        deps_dt_p = variables["Positive electrode porosity change"]
        deps_dt = pybamm.concatenation(deps_dt_s, deps_dt_p)

        c_ox = variables["Separator and positive electrode oxygen concentration"]
        N_ox = variables["Oxygen flux"].orphans[1]

        j_ox = variables["Positive electrode oxygen interfacial current density"]
        source_terms = pybamm.concatenation(
            pybamm.FullBroadcast(0, "separator", "current collector"),
            param.s_ox_Ox * j_ox,
        )

        self.rhs = {
            c_ox: (1 / eps)
            * (-pybamm.div(N_ox) / param.C_e + source_terms - c_ox * deps_dt)
        }
Esempio n. 22
0
    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)
Esempio n. 23
0
    def set_algebraic(self, variables):
        phi_e = variables["Electrolyte potential"]
        i_e = variables["Electrolyte current density"]

        # Variable summing all of the interfacial current densities
        sum_j = variables["Sum of interfacial current densities"]

        self.algebraic = {phi_e: pybamm.div(i_e) - sum_j}
Esempio n. 24
0
    def set_algebraic(self, variables):

        phi_s = variables[self.domain + " electrode potential"]
        i_s = variables[self.domain + " electrode current density"]
        sum_j = sum(variables[reaction[self.domain]["aj"]]
                    for reaction in self.reactions.values())

        self.algebraic[phi_s] = pybamm.div(i_s) + sum_j
Esempio n. 25
0
    def set_algebraic(self, variables):
        p = variables["Electrolyte pressure"]
        j = variables["Interfacial current density"]
        v_box = variables["Volume-averaged velocity"]
        dVbox_dz = variables["Vertical volume-averaged acceleration"]

        self.algebraic = {
            p: pybamm.div(v_box) + dVbox_dz - self.param.beta * j
        }
    def set_rhs(self, variables):
        T = variables["Cell temperature"]
        q = variables["Heat flux"]
        Q = variables["Total heating"]

        self.rhs = {
            T: (-pybamm.div(q) / self.param.delta**2 + self.param.B * Q) /
            (self.param.C_th * self.param.rho_k)
        }
Esempio n. 27
0
    def test_grad_div_shapes_mixed_domain(self):
        """
        Test grad and div with Dirichlet boundary conditions (applied by grad on var)
        """
        # create discretisation
        mesh = get_mesh_for_testing()
        spatial_methods = {"macroscale": pybamm.SpectralVolume()}
        disc = pybamm.Discretisation(mesh, spatial_methods)

        # grad
        var = pybamm.Variable("var",
                              domain=["negative electrode", "separator"])
        grad_eqn = pybamm.grad(var)
        boundary_conditions = {
            var.id: {
                "left": (pybamm.Scalar(1), "Dirichlet"),
                "right": (pybamm.Scalar(1), "Dirichlet"),
            }
        }
        disc.bcs = boundary_conditions

        disc.set_variable_slices([var])

        grad_eqn_disc = disc.process_symbol(grad_eqn)

        combined_submesh = mesh.combine_submeshes("negative electrode",
                                                  "separator")
        constant_y = np.ones_like(combined_submesh.nodes[:, np.newaxis])
        np.testing.assert_array_almost_equal(
            grad_eqn_disc.evaluate(None, constant_y),
            np.zeros_like(combined_submesh.edges[:, np.newaxis]),
        )

        # div: test on linear y (should have laplacian zero) so change bcs
        linear_y = combined_submesh.nodes
        N = pybamm.grad(var)
        div_eqn = pybamm.div(N)
        boundary_conditions = {
            var.id: {
                "left": (pybamm.Scalar(0), "Dirichlet"),
                "right":
                (pybamm.Scalar(combined_submesh.edges[-1]), "Dirichlet"),
            }
        }
        disc.bcs = boundary_conditions

        grad_eqn_disc = disc.process_symbol(grad_eqn)
        np.testing.assert_array_almost_equal(
            grad_eqn_disc.evaluate(None, linear_y),
            np.ones_like(combined_submesh.edges[:, np.newaxis]),
        )

        div_eqn_disc = disc.process_symbol(div_eqn)
        np.testing.assert_array_almost_equal(
            div_eqn_disc.evaluate(None, linear_y),
            np.zeros_like(combined_submesh.nodes[:, np.newaxis]),
        )
    def set_algebraic(self, variables):
        if self.domain == "Separator":
            return

        delta_phi = variables[self.domain +
                              " electrode surface potential difference"]
        i_e = variables[self.domain + " electrolyte current density"]
        sum_j = sum(variables[reaction[self.domain]["aj"]]
                    for reaction in self.reactions.values())
        self.algebraic[delta_phi] = pybamm.div(i_e) - sum_j
Esempio n. 29
0
    def set_algebraic(self, variables):

        phi_s = variables[self.domain + " electrode potential"]
        i_s = variables[self.domain + " electrode current density"]

        # Variable summing all of the interfacial current densities
        sum_j = variables["Sum of " + self.domain.lower() +
                          " electrode interfacial current densities"]

        self.algebraic[phi_s] = pybamm.div(i_s) + sum_j
Esempio n. 30
0
    def test_discretise_spatial_operator(self):
        # create discretisation
        whole_cell = ["negative electrode", "separator", "positive electrode"]
        var = pybamm.Variable("var", domain=whole_cell)
        disc = get_discretisation_for_testing()
        mesh = disc.mesh
        variables = [var]
        disc.set_variable_slices(variables)

        # Simple expressions
        for eqn in [pybamm.grad(var), pybamm.div(var)]:
            eqn_disc = disc.process_symbol(eqn)

            self.assertIsInstance(eqn_disc, pybamm.MatrixMultiplication)
            self.assertIsInstance(eqn_disc.children[0], pybamm.Matrix)
            self.assertIsInstance(eqn_disc.children[1], pybamm.StateVector)

            combined_submesh = mesh.combine_submeshes(*whole_cell)
            y = combined_submesh[0].nodes**2
            var_disc = disc.process_symbol(var)
            # grad and var are identity operators here (for testing purposes)
            np.testing.assert_array_equal(eqn_disc.evaluate(None, y),
                                          var_disc.evaluate(None, y))

        # More complex expressions
        for eqn in [var * pybamm.grad(var), var * pybamm.div(var)]:
            eqn_disc = disc.process_symbol(eqn)

            self.assertIsInstance(eqn_disc, pybamm.Multiplication)
            self.assertIsInstance(eqn_disc.children[0], pybamm.StateVector)
            self.assertIsInstance(eqn_disc.children[1],
                                  pybamm.MatrixMultiplication)
            self.assertIsInstance(eqn_disc.children[1].children[0],
                                  pybamm.Matrix)
            self.assertIsInstance(eqn_disc.children[1].children[1],
                                  pybamm.StateVector)

            y = combined_submesh[0].nodes**2
            var_disc = disc.process_symbol(var)
            # grad and var are identity operators here (for testing purposes)
            np.testing.assert_array_equal(eqn_disc.evaluate(None, y),
                                          var_disc.evaluate(None, y)**2)