コード例 #1
0
    def get_coupled_variables(self, variables):

        eps = separator_and_positive_only(variables["Porosity"])
        c_ox = variables[
            "Separator and positive electrode oxygen concentration"]
        # TODO: allow charge and convection?
        v_box = pybamm.Scalar(0)

        param = self.param

        b = pybamm.Concatenation(
            pybamm.FullBroadcast(param.b_s, ["separator"],
                                 "current collector"),
            pybamm.FullBroadcast(param.b_p, ["positive electrode"],
                                 "current collector"),
        )

        N_ox_diffusion = -(eps**b) * param.curlyD_ox * pybamm.grad(c_ox)

        N_ox = N_ox_diffusion + c_ox * v_box
        # Flux in the negative electrode is zero
        N_ox = pybamm.Concatenation(
            pybamm.FullBroadcast(0, "negative electrode", "current collector"),
            N_ox)

        variables.update(self._get_standard_flux_variables(N_ox))

        return variables
コード例 #2
0
    def _get_whole_cell_variables(self, variables):
        """
        A private function to obtain the potential and current concatenated
        across the whole cell. Note: requires 'variables' to contain the potential
        and current in the subdomains: 'negative electrode', 'separator', and
        'positive electrode'.

        Parameters
        ----------
        variables : dict
            The variables that have been set in the rest of the model.

        Returns
        -------
        variables : dict
            The variables including the whole-cell electrolyte potentials
            and currents.
        """

        phi_e_n = variables["Negative electrolyte potential"]
        phi_e_s = variables["Separator electrolyte potential"]
        phi_e_p = variables["Positive electrolyte potential"]
        phi_e = pybamm.Concatenation(phi_e_n, phi_e_s, phi_e_p)
        phi_e_av = pybamm.x_average(phi_e)

        i_e_n = variables["Negative electrolyte current density"]
        i_e_s = variables["Separator electrolyte current density"]
        i_e_p = variables["Positive electrolyte current density"]
        i_e = pybamm.Concatenation(i_e_n, i_e_s, i_e_p)

        variables.update(
            self._get_standard_potential_variables(phi_e, phi_e_av))
        variables.update(self._get_standard_current_variables(i_e))

        return variables
コード例 #3
0
ファイル: test_symbol.py プロジェクト: tinosulzer/PyBaMM
    def test_shape_and_size_for_testing(self):
        scal = pybamm.Scalar(1)
        self.assertEqual(scal.shape_for_testing, scal.shape)
        self.assertEqual(scal.size_for_testing, scal.size)

        state = pybamm.StateVector(slice(10, 25))
        self.assertEqual(state.shape_for_testing, state.shape)

        param = pybamm.Parameter("a")
        self.assertEqual(param.shape_for_testing, ())

        func = pybamm.FunctionParameter("func", state)
        self.assertEqual(func.shape_for_testing, state.shape_for_testing)

        concat = pybamm.Concatenation()
        self.assertEqual(concat.shape_for_testing, (0, ))
        concat = pybamm.Concatenation(state, state)
        self.assertEqual(concat.shape_for_testing, (30, 1))
        self.assertEqual(concat.size_for_testing, 30)

        var = pybamm.Variable("var", domain="negative electrode")
        broadcast = pybamm.Broadcast(0, "negative electrode")
        self.assertEqual(var.shape_for_testing, broadcast.shape_for_testing)
        self.assertEqual((var + broadcast).shape_for_testing,
                         broadcast.shape_for_testing)

        var = pybamm.Variable("var", domain=["random domain", "other domain"])
        broadcast = pybamm.Broadcast(0, ["random domain", "other domain"])
        self.assertEqual(var.shape_for_testing, broadcast.shape_for_testing)
        self.assertEqual((var + broadcast).shape_for_testing,
                         broadcast.shape_for_testing)

        sym = pybamm.Symbol("sym")
        with self.assertRaises(NotImplementedError):
            sym.shape_for_testing
コード例 #4
0
    def get_fundamental_variables(self):

        eps_n_av = self.param.epsilon_n
        eps_s_av = self.param.epsilon_s
        eps_p_av = self.param.epsilon_p

        eps_n = pybamm.FullBroadcast(
            eps_n_av, "negative electrode", "current collector"
        )
        eps_s = pybamm.FullBroadcast(eps_s_av, "separator", "current collector")
        eps_p = pybamm.FullBroadcast(
            eps_p_av, "positive electrode", "current collector"
        )
        eps = pybamm.Concatenation(eps_n, eps_s, eps_p)

        deps_n_dt = pybamm.FullBroadcast(0, "negative electrode", "current collector")
        deps_s_dt = pybamm.FullBroadcast(0, "separator", "current collector")
        deps_p_dt = pybamm.FullBroadcast(0, "positive electrode", "current collector")
        deps_dt = pybamm.Concatenation(deps_n_dt, deps_s_dt, deps_p_dt)

        variables = self._get_standard_porosity_variables(eps, set_leading_order=True)
        variables.update(
            self._get_standard_porosity_change_variables(
                deps_dt, set_leading_order=True
            )
        )

        return variables
コード例 #5
0
    def test_jac_of_domain_concatenation(self):
        # create mesh
        disc = get_1p1d_discretisation_for_testing()
        mesh = disc.mesh
        y = pybamm.StateVector(slice(0, 1500))

        # Jacobian of a DomainConcatenation of constants is a zero matrix of the
        # appropriate size
        a_dom = ["negative electrode"]
        b_dom = ["separator"]
        c_dom = ["positive electrode"]
        cc_npts = mesh["current collector"][0].npts
        curr_coll_vector = pybamm.Vector(np.ones(cc_npts), domain="current collector")
        a = 2 * pybamm.PrimaryBroadcast(curr_coll_vector, a_dom)
        b = pybamm.PrimaryBroadcast(curr_coll_vector, b_dom)
        c = 3 * pybamm.PrimaryBroadcast(curr_coll_vector, c_dom)

        conc = pybamm.Concatenation(a, b, c)
        disc.set_variable_slices([conc])
        conc_disc = disc.process_symbol(conc)
        jac = conc_disc.jac(y).evaluate().toarray()
        np.testing.assert_array_equal(jac, np.zeros((1500, 1500)))

        # Jacobian of a DomainConcatenation of StateVectors
        a = pybamm.Variable("a", domain=a_dom)
        b = pybamm.Variable("b", domain=b_dom)
        c = pybamm.Variable("c", domain=c_dom)
        conc = pybamm.Concatenation(a, b, c)
        disc.set_variable_slices([conc])
        conc_disc = disc.process_symbol(conc)
        y0 = np.ones(1500)
        jac = conc_disc.jac(y).evaluate(y=y0).toarray()
        np.testing.assert_array_equal(jac, np.eye(1500))
コード例 #6
0
 def test_public_functions(self):
     param = pybamm.LeadAcidParameters()
     a = pybamm.Scalar(0)
     variables = {
         "Porosity": pybamm.Concatenation(
             pybamm.FullBroadcast(a, "negative electrode", "current collector"),
             pybamm.FullBroadcast(a, "separator", "current collector"),
             pybamm.FullBroadcast(a, "positive electrode", "current collector"),
         ),
         "Electrolyte tortuosity": pybamm.Concatenation(
             pybamm.FullBroadcast(a, "negative electrode", "current collector"),
             pybamm.FullBroadcast(a, "separator", "current collector"),
             pybamm.FullBroadcast(a, "positive electrode", "current collector"),
         ),
         "Porosity change": pybamm.Concatenation(
             pybamm.FullBroadcast(a, "negative electrode", "current collector"),
             pybamm.FullBroadcast(a, "separator", "current collector"),
             pybamm.FullBroadcast(a, "positive electrode", "current collector"),
         ),
         "Volume-averaged velocity": a,
         "Negative electrode interfacial current density": pybamm.FullBroadcast(
             a, "negative electrode", "current collector"
         ),
         "Positive electrode interfacial current density": pybamm.FullBroadcast(
             a, "positive electrode", "current collector"
         ),
         "Positive electrode oxygen interfacial current "
         "density": pybamm.FullBroadcast(
             a, "positive electrode", "current collector"
         ),
     }
     submodel = pybamm.oxygen_diffusion.Full(param)
     std_tests = tests.StandardSubModelTests(submodel, variables)
     std_tests.test_all()
コード例 #7
0
    def _get_coupled_variables_from_potential(self, variables, phi_e_av):
        i_boundary_cc = variables["Current collector current density"]

        param = self.param
        l_n = param.l_n
        l_p = param.l_p
        x_n = pybamm.standard_spatial_vars.x_n
        x_p = pybamm.standard_spatial_vars.x_p

        phi_e_n = pybamm.PrimaryBroadcast(phi_e_av, ["negative electrode"])
        phi_e_s = pybamm.PrimaryBroadcast(phi_e_av, ["separator"])
        phi_e_p = pybamm.PrimaryBroadcast(phi_e_av, ["positive electrode"])
        phi_e = pybamm.Concatenation(phi_e_n, phi_e_s, phi_e_p)

        i_e_n = pybamm.outer(i_boundary_cc, x_n / l_n)
        i_e_s = pybamm.PrimaryBroadcast(i_boundary_cc, ["separator"])
        i_e_p = pybamm.outer(i_boundary_cc, (1 - x_p) / l_p)
        i_e = pybamm.Concatenation(i_e_n, i_e_s, i_e_p)

        variables.update(self._get_standard_potential_variables(phi_e, phi_e_av))
        variables.update(self._get_standard_current_variables(i_e))

        eta_c_av = pybamm.Scalar(0)  # concentration overpotential
        delta_phi_e_av = pybamm.Scalar(0)  # ohmic losses
        variables.update(self._get_split_overpotential(eta_c_av, delta_phi_e_av))

        return variables
コード例 #8
0
    def _get_standard_whole_cell_exchange_current_variables(self, variables):

        i_typ = self.param.i_typ
        L_x = self.param.L_x
        j_n_scale = i_typ / (self.param.a_n_dim * L_x)
        j_p_scale = i_typ / (self.param.a_p_dim * L_x)

        j0_n = variables[
            "Negative electrode" + self.reaction_name + " exchange current density"
        ]
        j0_s = pybamm.FullBroadcast(0, "separator", "current collector")
        j0_p = variables[
            "Positive electrode" + self.reaction_name + " exchange current density"
        ]
        j0 = pybamm.Concatenation(j0_n, j0_s, j0_p)
        j0_dim = pybamm.Concatenation(j_n_scale * j0_n, j0_s, j_p_scale * j0_p)

        if self.reaction_name == "":
            variables = {
                "Exchange current density": j0,
                "Exchange current density [A.m-2]": j0_dim,
                "Exchange current density per volume [A.m-3]": i_typ / L_x * j0,
            }
        else:
            reaction_name = self.reaction_name[1:].capitalize()
            variables = {
                reaction_name + " exchange current density": j0,
                reaction_name + " exchange current density [A.m-2]": j0_dim,
                reaction_name
                + " exchange current density per volume [A.m-3]": i_typ / L_x * j0,
            }

        return variables
コード例 #9
0
ファイル: test_symbol.py プロジェクト: soroscaliban/PyBaMM
    def test_symbol_visualise(self):

        param = pybamm.standard_parameters_lithium_ion

        one_n = pybamm.FullBroadcast(1, ["negative electrode"],
                                     "current collector")
        one_p = pybamm.FullBroadcast(1, ["positive electrode"],
                                     "current collector")

        zero_n = pybamm.FullBroadcast(0, ["negative electrode"],
                                      "current collector")
        zero_s = pybamm.FullBroadcast(0, ["separator"], "current collector")
        zero_p = pybamm.FullBroadcast(0, ["positive electrode"],
                                      "current collector")

        deps_dt = pybamm.Concatenation(zero_n, zero_s, zero_p)

        v_box = pybamm.Scalar(0)

        variables = {
            "Porosity": param.epsilon,
            "Electrolyte tortuosity": param.epsilon**1.5,
            "Porosity change": deps_dt,
            "Volume-averaged velocity": v_box,
            "Negative electrode interfacial current density": one_n,
            "Positive electrode interfacial current density": one_p,
            "Cell temperature": pybamm.Concatenation(zero_n, zero_s, zero_p),
        }
        icd = " interfacial current density"
        reactions = {
            "main": {
                "Negative": {
                    "s": 1,
                    "aj": "Negative electrode" + icd
                },
                "Positive": {
                    "s": 1,
                    "aj": "Positive electrode" + icd
                },
            }
        }
        model = pybamm.electrolyte.stefan_maxwell.diffusion.Full(
            param, reactions)
        variables.update(model.get_fundamental_variables())
        variables.update(model.get_coupled_variables(variables))

        model.set_rhs(variables)

        c_e = pybamm.standard_variables.c_e
        rhs = model.rhs[c_e]
        rhs.visualise("StefanMaxwell_test.png")
        self.assertTrue(os.path.exists("StefanMaxwell_test.png"))
        with self.assertRaises(ValueError):
            rhs.visualise("StefanMaxwell_test")
コード例 #10
0
    def get_coupled_variables(self, variables):

        param = self.param
        l_n = param.l_n
        l_s = param.l_s
        l_p = param.l_p
        x_s = pybamm.standard_spatial_vars.x_s
        x_p = pybamm.standard_spatial_vars.x_p

        # Unpack
        tor_s_0_av = variables["Leading-order x-averaged separator tortuosity"]
        tor_p_0_av = variables[
            "Leading-order x-averaged positive electrolyte tortuosity"
        ]

        # Diffusivities
        D_ox_s = tor_s_0_av * param.curlyD_ox
        D_ox_p = tor_p_0_av * param.curlyD_ox

        # Reactions
        sj_ox_p = sum(
            reaction["Positive"]["s_ox"]
            * variables[
                "Leading-order x-averaged " + reaction["Positive"]["aj"].lower()
            ]
            for reaction in self.reactions.values()
        )

        # Fluxes
        N_ox_n_1 = pybamm.FullBroadcast(0, "negative electrode", "current collector")
        N_ox_s_1 = -pybamm.PrimaryBroadcast(sj_ox_p * l_p, "separator")
        N_ox_p_1 = sj_ox_p * (x_p - 1)

        # Concentrations
        c_ox_n_1 = pybamm.FullBroadcast(0, "negative electrode", "current collector")
        c_ox_s_1 = sj_ox_p * l_p / D_ox_s * (x_s - l_n)
        c_ox_p_1 = (
            -sj_ox_p / (2 * D_ox_p) * ((x_p - 1) ** 2 - l_p ** 2)
            + sj_ox_p * l_p * l_s / D_ox_s
        )

        # Update variables
        c_ox = pybamm.Concatenation(
            param.C_e * c_ox_n_1, param.C_e * c_ox_s_1, param.C_e * c_ox_p_1
        )
        variables.update(self._get_standard_concentration_variables(c_ox))

        N_ox = pybamm.Concatenation(
            param.C_e * N_ox_n_1, param.C_e * N_ox_s_1, param.C_e * N_ox_p_1
        )
        variables.update(self._get_standard_flux_variables(N_ox))

        return variables
コード例 #11
0
    def test_concatenation_domains(self):
        a = pybamm.Symbol("a", domain=["negative electrode"])
        b = pybamm.Symbol("b", domain=["separator", "positive electrode"])
        c = pybamm.Symbol("c", domain=["test"])
        conc = pybamm.Concatenation(a, b, c)
        self.assertEqual(
            conc.domain,
            ["negative electrode", "separator", "positive electrode", "test"],
        )

        # Can't concatenate nodes with overlapping domains
        d = pybamm.Symbol("d", domain=["separator"])
        with self.assertRaises(pybamm.DomainError):
            pybamm.Concatenation(a, b, d)
コード例 #12
0
 def test_public_functions(self):
     param = pybamm.standard_parameters_lead_acid
     a = pybamm.Scalar(0)
     variables = {
         "Porosity":
         pybamm.Concatenation(
             pybamm.FullBroadcast(a, "negative electrode",
                                  "current collector"),
             pybamm.FullBroadcast(a, "separator", "current collector"),
             pybamm.FullBroadcast(a, "positive electrode",
                                  "current collector"),
         ),
         "Electrolyte tortuosity":
         pybamm.Concatenation(
             pybamm.FullBroadcast(a, "negative electrode",
                                  "current collector"),
             pybamm.FullBroadcast(a, "separator", "current collector"),
             pybamm.FullBroadcast(a, "positive electrode",
                                  "current collector"),
         ),
         "Porosity change":
         pybamm.Concatenation(
             pybamm.FullBroadcast(a, "negative electrode",
                                  "current collector"),
             pybamm.FullBroadcast(a, "separator", "current collector"),
             pybamm.FullBroadcast(a, "positive electrode",
                                  "current collector"),
         ),
         "Volume-averaged velocity":
         a,
         "Negative electrode interfacial current density":
         pybamm.FullBroadcast(a, "negative electrode", "current collector"),
         "Positive electrode interfacial current density":
         pybamm.FullBroadcast(a, "positive electrode", "current collector"),
     }
     reactions = {
         "main": {
             "Negative": {
                 "s_ox": param.s_ox_Ox,
                 "aj": "Negative electrode interfacial current density",
             },
             "Positive": {
                 "s_ox": param.s_ox_Ox,
                 "aj": "Positive electrode interfacial current density",
             },
         }
     }
     submodel = pybamm.oxygen_diffusion.Full(param, reactions)
     std_tests = tests.StandardSubModelTests(submodel, variables)
     std_tests.test_all()
コード例 #13
0
ファイル: thermal_parameters.py プロジェクト: yonas-y/PyBaMM
    def _set_dimensionless_parameters(self):
        "Defines the dimensionless parameters"

        # Density
        self.rho_cn = self.rho_cn_dim * self.c_p_cn_dim / self.rho_eff_dim
        self.rho_n = self.rho_n_dim * self.c_p_n_dim / self.rho_eff_dim
        self.rho_s = self.rho_s_dim * self.c_p_s_dim / self.rho_eff_dim
        self.rho_p = self.rho_p_dim * self.c_p_p_dim / self.rho_eff_dim
        self.rho_cp = self.rho_cp_dim * self.c_p_cp_dim / self.rho_eff_dim

        self.rho_k = pybamm.Concatenation(
            pybamm.FullBroadcast(
                self.rho_n, ["negative electrode"], "current collector"
            ),
            pybamm.FullBroadcast(self.rho_s, ["separator"], "current collector"),
            pybamm.FullBroadcast(
                self.rho_p, ["positive electrode"], "current collector"
            ),
        )

        # Thermal conductivity
        self.lambda_cn = self.lambda_cn_dim / self.lambda_eff_dim
        self.lambda_n = self.lambda_n_dim / self.lambda_eff_dim
        self.lambda_s = self.lambda_s_dim / self.lambda_eff_dim
        self.lambda_p = self.lambda_p_dim / self.lambda_eff_dim
        self.lambda_cp = self.lambda_cp_dim / self.lambda_eff_dim

        self.lambda_k = pybamm.Concatenation(
            pybamm.FullBroadcast(
                self.lambda_n, ["negative electrode"], "current collector"
            ),
            pybamm.FullBroadcast(self.lambda_s, ["separator"], "current collector"),
            pybamm.FullBroadcast(
                self.lambda_p, ["positive electrode"], "current collector"
            ),
        )

        # Relative temperature rise
        self.Theta = self.Delta_T / self.T_ref

        # Cooling coefficient
        self.h_cn = self.h_cn_dim * self.geo.L_x / self.lambda_eff_dim
        self.h_cp = self.h_cp_dim * self.geo.L_x / self.lambda_eff_dim
        self.h_tab_n = self.h_tab_n_dim * self.geo.L_x / self.lambda_eff_dim
        self.h_tab_p = self.h_tab_p_dim * self.geo.L_x / self.lambda_eff_dim
        self.h_edge = self.h_edge_dim * self.geo.L_x / self.lambda_eff_dim
        self.h_total = self.h_total_dim * self.geo.L_x / self.lambda_eff_dim

        # Initial temperature
        self.T_init = (self.T_init_dim - self.T_ref) / self.Delta_T
コード例 #14
0
ファイル: test_lead_acid.py プロジェクト: yushun9897/PyBaMM
 def setUp(self):
     c_e_n = pybamm.Variable("concentration", domain=["negative electrode"])
     c_e_s = pybamm.Variable("concentration", domain=["separator"])
     c_e_p = pybamm.Variable("concentration", domain=["positive electrode"])
     self.c_e = pybamm.Concatenation(c_e_n, c_e_s, c_e_p)
     T_n = pybamm.Variable("temperature", domain=["negative electrode"])
     T_s = pybamm.Variable("temperature", domain=["separator"])
     T_p = pybamm.Variable("temperature", domain=["positive electrode"])
     self.T = pybamm.Concatenation(T_n, T_s, T_p)
     self.variables = {
         "Negative electrolyte concentration": c_e_n,
         "Positive electrolyte concentration": c_e_p,
         "Negative electrode temperature": T_n,
         "Positive electrode temperature": T_p,
     }
コード例 #15
0
 def test_base_concatenation(self):
     a = pybamm.Symbol("a")
     b = pybamm.Symbol("b")
     c = pybamm.Symbol("c")
     conc = pybamm.Concatenation(a, b, c)
     self.assertEqual(conc.name, "concatenation")
     self.assertIsInstance(conc.children[0], pybamm.Symbol)
     self.assertEqual(conc.children[0].name, "a")
     self.assertEqual(conc.children[1].name, "b")
     self.assertEqual(conc.children[2].name, "c")
     d = pybamm.Vector(np.array([2]))
     e = pybamm.Vector(np.array([1]))
     f = pybamm.Vector(np.array([3]))
     conc2 = pybamm.Concatenation(d, e, f)
     with self.assertRaises(TypeError):
         conc2.evaluate()
コード例 #16
0
ファイル: test_discretisation.py プロジェクト: js1tr3/PyBaMM
    def test_adding_2D_external_variable_fail(self):
        model = pybamm.BaseModel()
        a = pybamm.Variable(
            "a",
            domain=["negative electrode", "separator"],
            auxiliary_domains={"secondary": "current collector"},
        )
        b1 = pybamm.Variable(
            "b",
            domain="negative electrode",
            auxiliary_domains={"secondary": "current collector"},
        )
        b2 = pybamm.Variable(
            "b",
            domain="separator",
            auxiliary_domains={"secondary": "current collector"},
        )
        b = pybamm.Concatenation(b1, b2)

        model.rhs = {a: a * b}
        model.initial_conditions = {a: 0}
        model.external_variables = [b]
        model.variables = {"b": b}

        disc = get_1p1d_discretisation_for_testing()
        with self.assertRaisesRegex(
            NotImplementedError, "Cannot create 2D external variable"
        ):
            disc.process_model(model)
コード例 #17
0
ファイル: test_discretisation.py プロジェクト: js1tr3/PyBaMM
    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)
コード例 #18
0
    def test_concatenation_2D(self):
        disc = get_1p1d_discretisation_for_testing(zpts=3)

        a = pybamm.Variable("a", domain=["negative electrode"])
        b = pybamm.Variable("b", domain=["separator"])
        c = pybamm.Variable("c", domain=["positive electrode"])
        conc = pybamm.Concatenation(a, b, c)
        disc.set_variable_slices([conc])
        self.assertEqual(
            disc.y_slices[a.id],
            [slice(0, 40), slice(100, 140),
             slice(200, 240)])
        self.assertEqual(
            disc.y_slices[b.id],
            [slice(40, 65), slice(140, 165),
             slice(240, 265)])
        self.assertEqual(
            disc.y_slices[c.id],
            [slice(65, 100), slice(165, 200),
             slice(265, 300)])
        expr = disc.process_symbol(conc)
        self.assertIsInstance(expr, pybamm.DomainConcatenation)

        # Evaulate
        y = np.linspace(0, 1, 300)
        self.assertEqual(expr.children[0].evaluate(0, y).shape, (120, 1))
        self.assertEqual(expr.children[1].evaluate(0, y).shape, (75, 1))
        self.assertEqual(expr.children[2].evaluate(0, y).shape, (105, 1))
        np.testing.assert_equal(expr.evaluate(0, y), y[:, np.newaxis])
コード例 #19
0
    def test_domain_concatenation_2D(self):
        disc = get_1p1d_discretisation_for_testing()

        a_dom = ["negative electrode"]
        b_dom = ["separator"]
        a = pybamm.Variable("a", domain=a_dom)
        b = pybamm.Variable("b", domain=b_dom)
        conc = pybamm.concatenation(2 * a, 3 * b)
        disc.set_variable_slices([a, b])
        expr = disc.process_symbol(conc)
        self.assertIsInstance(expr, pybamm.DomainConcatenation)

        y = np.empty((expr._size, 1))
        for i in range(len(y)):
            y[i] = i

        constant_symbols = OrderedDict()
        variable_symbols = OrderedDict()
        pybamm.find_symbols(expr, constant_symbols, variable_symbols)

        self.assertEqual(len(constant_symbols), 0)

        evaluator = pybamm.EvaluatorPython(expr)
        result = evaluator.evaluate(y=y)
        np.testing.assert_allclose(result, expr.evaluate(y=y))

        # check that concatenating a single domain is consistent
        expr = disc.process_symbol(pybamm.Concatenation(a))
        evaluator = pybamm.EvaluatorPython(expr)
        result = evaluator.evaluate(y=y)
        np.testing.assert_allclose(result, expr.evaluate(y=y))
コード例 #20
0
    def _get_standard_porosity_change_variables(
        self, deps_n_dt, deps_s_dt, deps_p_dt, set_leading_order=False
    ):

        deps_n_dt_av = pybamm.x_average(deps_n_dt)
        deps_s_dt_av = pybamm.x_average(deps_s_dt)
        deps_p_dt_av = pybamm.x_average(deps_p_dt)
        deps_dt = pybamm.Concatenation(deps_n_dt, deps_s_dt, deps_p_dt)

        variables = {
            "Porosity change": deps_dt,
            "Negative electrode porosity change": deps_n_dt,
            "Separator porosity change": deps_s_dt,
            "Positive electrode porosity change": deps_p_dt,
            "X-averaged negative electrode porosity change": deps_n_dt_av,
            "X-averaged separator porosity change": deps_s_dt_av,
            "X-averaged positive electrode porosity change": deps_p_dt_av,
        }

        if set_leading_order is True:
            variables.update(
                {
                    "Leading-order x-averaged "
                    + "negative electrode porosity change": deps_n_dt_av,
                    "Leading-order x-averaged separator porosity change": deps_s_dt_av,
                    "Leading-order x-averaged "
                    + "positive electrode porosity change": deps_p_dt_av,
                }
            )

        return variables
コード例 #21
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)
        }
コード例 #22
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:
            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)
        }
コード例 #23
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)
        }
コード例 #24
0
    def get_coupled_variables(self, variables):
        param = self.param
        x_n = pybamm.standard_spatial_vars.x_n
        x_p = pybamm.standard_spatial_vars.x_p
        # j_n = variables["Negative electrode interfacial current density"]
        # j_p = variables["Positive electrode interfacial current density"]

        # Volume-averaged velocity
        # v_box_n = param.beta_n * pybamm.IndefiniteIntegral(j_n, x_n)
        # # Shift v_box_p to be equal to 0 at x_p = 1
        # v_box_p = param.beta_p * (
        #     pybamm.IndefiniteIntegral(j_p, x_p) - pybamm.Integral(j_p, x_p)
        # )
        j_n_av = variables[
            "X-averaged negative electrode interfacial current density"]
        j_p_av = variables[
            "X-averaged positive electrode interfacial current density"]

        # Volume-averaged velocity
        v_box_n = param.beta_n * pybamm.outer(j_n_av, x_n)
        v_box_p = param.beta_p * pybamm.outer(j_p_av, x_p - 1)

        v_box_s, dVbox_dz = self._separator_velocity(variables)
        v_box = pybamm.Concatenation(v_box_n, v_box_s, v_box_p)

        variables.update(self._get_standard_velocity_variables(v_box))
        variables.update(
            self._get_standard_vertical_velocity_variables(dVbox_dz))

        return variables
コード例 #25
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)
        }
コード例 #26
0
ファイル: base_convection.py プロジェクト: yushun9897/PyBaMM
    def _get_standard_whole_cell_velocity_variables(self, variables):
        """
        A private function to obtain the standard variables which
        can be derived from the fluid velocity.

        Parameters
        ----------
        variables : dict
            The existing variables in the model

        Returns
        -------
        variables : dict
            The variables which can be derived from the volume-averaged
            velocity.
        """

        vel_scale = self.param.velocity_scale

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

        v_box = pybamm.Concatenation(v_box_n, v_box_s, v_box_p)

        variables = {
            "Volume-averaged velocity": v_box,
            "Volume-averaged velocity [m.s-1]": vel_scale * v_box,
        }

        return variables
コード例 #27
0
    def test_concatenations(self):
        y = np.linspace(0, 1, 10)[:, np.newaxis]
        a = pybamm.Vector(y)
        b = pybamm.Scalar(16)
        c = pybamm.Scalar(3)
        conc = pybamm.NumpyConcatenation(a, b, c)
        self.assert_casadi_equal(conc.to_casadi(),
                                 casadi.MX(conc.evaluate()),
                                 evalf=True)

        # Domain concatenation
        mesh = get_mesh_for_testing()
        a_dom = ["negative electrode"]
        b_dom = ["separator"]
        a = 2 * pybamm.Vector(np.ones_like(mesh[a_dom[0]].nodes), domain=a_dom)
        b = pybamm.Vector(np.ones_like(mesh[b_dom[0]].nodes), domain=b_dom)
        conc = pybamm.DomainConcatenation([b, a], mesh)
        self.assert_casadi_equal(conc.to_casadi(),
                                 casadi.MX(conc.evaluate()),
                                 evalf=True)

        # 2d
        disc = get_1p1d_discretisation_for_testing()
        a = pybamm.Variable("a", domain=a_dom)
        b = pybamm.Variable("b", domain=b_dom)
        conc = pybamm.Concatenation(a, b)
        disc.set_variable_slices([conc])
        expr = disc.process_symbol(conc)
        y = casadi.SX.sym("y", expr.size)
        x = expr.to_casadi(None, y)
        f = casadi.Function("f", [x], [x])
        y_eval = np.linspace(0, 1, expr.size)
        self.assert_casadi_equal(f(y_eval), casadi.SX(expr.evaluate(y=y_eval)))
コード例 #28
0
    def test_grad_1plus1d(self):
        mesh = get_1p1d_mesh_for_testing()
        spatial_methods = {"macroscale": pybamm.FiniteVolume()}
        disc = pybamm.Discretisation(mesh, spatial_methods)

        a = pybamm.Variable("a", domain=["negative electrode"])
        b = pybamm.Variable("b", domain=["separator"])
        c = pybamm.Variable("c", domain=["positive electrode"])
        var = pybamm.Concatenation(a, b, c)
        boundary_conditions = {
            var.id: {
                "left": (pybamm.Vector(np.linspace(0, 1, 15)), "Neumann"),
                "right": (pybamm.Vector(np.linspace(0, 1, 15)), "Neumann"),
            }
        }

        disc.bcs = boundary_conditions
        disc.set_variable_slices([var])
        grad_eqn_disc = disc.process_symbol(pybamm.grad(var))

        # Evaulate
        combined_submesh = mesh.combine_submeshes(*var.domain)
        linear_y = np.outer(np.linspace(0, 1, 15),
                            combined_submesh[0].nodes).reshape(-1, 1)

        expected = np.outer(np.linspace(0, 1, 15),
                            np.ones_like(combined_submesh[0].edges)).reshape(
                                -1, 1)
        np.testing.assert_array_almost_equal(
            grad_eqn_disc.evaluate(None, linear_y), expected)
コード例 #29
0
    def test_symbol_visualise(self):

        param = pybamm.LithiumIonParameters()

        zero_n = pybamm.FullBroadcast(0, ["negative electrode"],
                                      "current collector")
        zero_s = pybamm.FullBroadcast(0, ["separator"], "current collector")
        zero_p = pybamm.FullBroadcast(0, ["positive electrode"],
                                      "current collector")

        zero_nsp = pybamm.Concatenation(zero_n, zero_s, zero_p)

        v_box = pybamm.Scalar(0)

        variables = {
            "Porosity":
            param.epsilon,
            "Electrolyte tortuosity":
            param.epsilon**1.5,
            "Porosity change":
            zero_nsp,
            "Electrolyte current density":
            zero_nsp,
            "Volume-averaged velocity":
            v_box,
            "Interfacial current density":
            zero_nsp,
            "Oxygen interfacial current density":
            zero_nsp,
            "Cell temperature":
            pybamm.Concatenation(zero_n, zero_s, zero_p),
            "Transverse volume-averaged acceleration":
            pybamm.Concatenation(zero_n, zero_s, zero_p),
            "Sum of electrolyte reaction source terms":
            zero_nsp,
        }
        model = pybamm.electrolyte_diffusion.Full(param)
        variables.update(model.get_fundamental_variables())
        variables.update(model.get_coupled_variables(variables))

        model.set_rhs(variables)

        rhs = list(model.rhs.values())[0]
        rhs.visualise("StefanMaxwell_test.png")
        self.assertTrue(os.path.exists("StefanMaxwell_test.png"))
        with self.assertRaises(ValueError):
            rhs.visualise("StefanMaxwell_test")
コード例 #30
0
    def get_fundamental_variables(self):
        c_e_av = pybamm.standard_variables.c_e_av
        c_e_n = pybamm.PrimaryBroadcast(c_e_av, ["negative electrode"])
        c_e_s = pybamm.PrimaryBroadcast(c_e_av, ["separator"])
        c_e_p = pybamm.PrimaryBroadcast(c_e_av, ["positive electrode"])
        c_e = pybamm.Concatenation(c_e_n, c_e_s, c_e_p)

        return self._get_standard_concentration_variables(c_e)