Exemplo n.º 1
0
    def test_definite_integral_vector(self):
        mesh = get_2p1d_mesh_for_testing(include_particles=False)
        spatial_methods = {
            "macroscale": pybamm.FiniteVolume(),
            "current collector": pybamm.ScikitFiniteElement(),
        }
        disc = pybamm.Discretisation(mesh, spatial_methods)
        var = pybamm.Variable("var", domain="current collector")
        disc.set_variable_slices([var])

        # row (default)
        vec = pybamm.DefiniteIntegralVector(var)
        vec_disc = disc.process_symbol(vec)
        self.assertEqual(vec_disc.shape[0], 1)
        self.assertEqual(vec_disc.shape[1], mesh["current collector"].npts)

        # column
        vec = pybamm.DefiniteIntegralVector(var, vector_type="column")
        vec_disc = disc.process_symbol(vec)
        self.assertEqual(vec_disc.shape[0], mesh["current collector"].npts)
        self.assertEqual(vec_disc.shape[1], 1)
Exemplo n.º 2
0
    def test_definite_integral_vector(self):
        mesh = get_mesh_for_testing()
        spatial_methods = {
            "macroscale": pybamm.FiniteVolume(),
            "negative particle": pybamm.FiniteVolume(),
            "positive particle": pybamm.FiniteVolume(),
        }
        disc = pybamm.Discretisation(mesh, spatial_methods)
        var = pybamm.Variable("var", domain="negative electrode")
        disc.set_variable_slices([var])

        # row (default)
        vec = pybamm.DefiniteIntegralVector(var)
        vec_disc = disc.process_symbol(vec)
        self.assertEqual(vec_disc.shape[0], 1)
        self.assertEqual(vec_disc.shape[1], mesh["negative electrode"][0].npts)

        # column
        vec = pybamm.DefiniteIntegralVector(var, vector_type="column")
        vec_disc = disc.process_symbol(vec)
        self.assertEqual(vec_disc.shape[0], mesh["negative electrode"][0].npts)
        self.assertEqual(vec_disc.shape[1], 1)
    def test_pure_neumann_poisson(self):
        # grad^2 u = 1, du/dz = 1 at z = 1, du/dn = 0 elsewhere, u has zero average
        u = pybamm.Variable("u", domain="current collector")
        c = pybamm.Variable("c")  # lagrange multiplier
        y = pybamm.SpatialVariable("y", ["current collector"])
        z = pybamm.SpatialVariable("z", ["current collector"])

        model = pybamm.BaseModel()
        # 0*c hack otherwise gives KeyError
        model.algebraic = {
            u:
            pybamm.laplacian(u) - pybamm.source(1, u) +
            c * pybamm.DefiniteIntegralVector(u, vector_type="column"),
            c:
            pybamm.Integral(u, [y, z]) + 0 * c,
        }
        model.initial_conditions = {u: pybamm.Scalar(0), c: pybamm.Scalar(0)}
        # set boundary conditions ("negative tab" = bottom of unit square,
        # "positive tab" = top of unit square, elsewhere normal derivative is zero)
        model.boundary_conditions = {
            u: {
                "negative tab": (0, "Neumann"),
                "positive tab": (1, "Neumann")
            }
        }
        model.variables = {"c": c, "u": u}
        # create discretisation
        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)
        disc.process_model(model)

        # solve model
        solver = pybamm.AlgebraicSolver()
        solution = solver.solve(model)

        z = mesh["current collector"].coordinates[1, :][:, np.newaxis]
        u_exact = z**2 / 2 - 1 / 6
        np.testing.assert_array_almost_equal(solution.y[:-1],
                                             u_exact,
                                             decimal=1)
    def __init__(self):
        super().__init__()
        self.name = "Effective resistance in current collector model"
        self.param = pybamm.standard_parameters_lithium_ion

        # Get useful parameters
        param = self.param
        l_cn = param.l_cn
        l_cp = param.l_cp
        l_y = param.l_y
        sigma_cn_dbl_prime = param.sigma_cn_dbl_prime
        sigma_cp_dbl_prime = param.sigma_cp_dbl_prime
        alpha_prime = param.alpha_prime

        # Set model variables
        var = pybamm.standard_spatial_vars

        psi = pybamm.Variable("Current collector potential weighted sum",
                              ["current collector"])
        W = pybamm.Variable(
            "Perturbation to current collector potential difference",
            ["current collector"],
        )
        c_psi = pybamm.Variable("Lagrange multiplier for variable `psi`")
        c_W = pybamm.Variable("Lagrange multiplier for variable `W`")

        self.variables = {
            "Current collector potential weighted sum": psi,
            "Perturbation to current collector potential difference": W,
            "Lagrange multiplier for variable `psi`": c_psi,
            "Lagrange multiplier for variable `W`": c_W,
        }

        # Algebraic equations (enforce zero mean constraint through Lagrange multiplier)
        # 0*LagrangeMultiplier hack otherwise gives KeyError
        self.algebraic = {
            psi:
            pybamm.laplacian(psi) +
            c_psi * pybamm.DefiniteIntegralVector(psi, vector_type="column"),
            W:
            pybamm.laplacian(W) - pybamm.source(1, W) +
            c_W * pybamm.DefiniteIntegralVector(W, vector_type="column"),
            c_psi:
            pybamm.Integral(psi, [var.y, var.z]) + 0 * c_psi,
            c_W:
            pybamm.Integral(W, [var.y, var.z]) + 0 * c_W,
        }

        # Boundary conditons
        psi_neg_tab_bc = l_cn
        psi_pos_tab_bc = -l_cp
        W_neg_tab_bc = l_y / (alpha_prime * sigma_cn_dbl_prime)
        W_pos_tab_bc = l_y / (alpha_prime * sigma_cp_dbl_prime)

        self.boundary_conditions = {
            psi: {
                "negative tab": (psi_neg_tab_bc, "Neumann"),
                "positive tab": (psi_pos_tab_bc, "Neumann"),
            },
            W: {
                "negative tab": (W_neg_tab_bc, "Neumann"),
                "positive tab": (W_pos_tab_bc, "Neumann"),
            },
        }

        # "Initial conditions" provides initial guess for solver
        # TODO: better guess than zero?
        self.initial_conditions = {
            psi: pybamm.Scalar(0),
            W: pybamm.Scalar(0),
            c_psi: pybamm.Scalar(0),
            c_W: pybamm.Scalar(0),
        }

        # Define effective current collector resistance
        psi_neg_tab = pybamm.BoundaryValue(psi, "negative tab")
        psi_pos_tab = pybamm.BoundaryValue(psi, "positive tab")
        W_neg_tab = pybamm.BoundaryValue(W, "negative tab")
        W_pos_tab = pybamm.BoundaryValue(W, "positive tab")

        R_cc = ((alpha_prime / l_y) * (sigma_cn_dbl_prime * l_cn * W_pos_tab +
                                       sigma_cp_dbl_prime * l_cp * W_neg_tab) -
                (psi_pos_tab - psi_neg_tab)) / (sigma_cn_dbl_prime * l_cn +
                                                sigma_cp_dbl_prime * l_cp)

        R_cc_dim = R_cc * param.potential_scale / param.I_typ

        self.variables.update({
            "Current collector potential weighted sum (negative tab)":
            psi_neg_tab,
            "Current collector potential weighted sum (positive tab)":
            psi_pos_tab,
            "Perturbation to c.c. potential difference (negative tab)":
            W_neg_tab,
            "Perturbation to c.c. potential difference (positive tab)":
            W_pos_tab,
            "Effective current collector resistance":
            R_cc,
            "Effective current collector resistance [Ohm]":
            R_cc_dim,
        })
Exemplo n.º 5
0
    def __init__(self):
        super().__init__()
        self.name = "Effective resistance in current collector model (2D)"
        self.param = pybamm.standard_parameters_lithium_ion

        # Get necessary parameters
        param = self.param
        l_cn = param.l_cn
        l_cp = param.l_cp
        l_tab_p = param.l_tab_p
        A_tab_p = l_cp * l_tab_p
        sigma_cn_dbl_prime = param.sigma_cn_dbl_prime
        sigma_cp_dbl_prime = param.sigma_cp_dbl_prime
        delta = param.delta

        # Set model variables -- we solve a auxilliary problem in each current collector
        # then relate this to the potentials and resistances later
        f_n = pybamm.Variable("Unit solution in negative current collector",
                              domain="current collector")
        f_p = pybamm.Variable("Unit solution in positive current collector",
                              domain="current collector")

        # Governing equations -- we impose that the average of f_p is zero
        # by introducing a Lagrange multiplier
        c = pybamm.Variable("Lagrange multiplier")

        self.algebraic = {
            f_n:
            pybamm.laplacian(f_n) + pybamm.source(1, f_n),
            c:
            pybamm.laplacian(f_p) - pybamm.source(1, f_p) +
            c * pybamm.DefiniteIntegralVector(f_p, vector_type="column"),
            f_p:
            pybamm.yz_average(f_p) + 0 * c,
        }

        # Boundary conditons
        pos_tab_bc = l_cp / A_tab_p
        self.boundary_conditions = {
            f_n: {
                "negative tab": (0, "Dirichlet"),
                "positive tab": (0, "Neumann")
            },
            f_p: {
                "negative tab": (0, "Neumann"),
                "positive tab": (pos_tab_bc, "Neumann"),
            },
        }

        # "Initial conditions" provides initial guess for solver
        self.initial_conditions = {
            f_n: pybamm.Scalar(0),
            f_p: pybamm.Scalar(0),
            c: pybamm.Scalar(0),
        }

        # Define effective current collector resistance
        R_cc_n = delta * pybamm.yz_average(f_n) / (l_cn * sigma_cn_dbl_prime)
        R_cc_p = (delta * pybamm.BoundaryIntegral(f_p, "positive tab") /
                  (l_cp * sigma_cp_dbl_prime))
        R_cc = R_cc_n + R_cc_p
        R_scale = param.potential_scale / param.I_typ

        self.variables = {
            "Unit solution in negative current collector":
            f_n,
            "Unit solution in positive current collector":
            f_p,
            "Effective current collector resistance":
            R_cc,
            "Effective current collector resistance [Ohm]":
            R_cc * R_scale,
            "Effective negative current collector resistance":
            R_cc_n,
            "Effective negative current collector resistance [Ohm]":
            R_cc_n * R_scale,
            "Effective positive current collector resistance":
            R_cc_p,
            "Effective positive current collector resistance [Ohm]":
            R_cc_p * R_scale,
        }

        # Add spatial variables
        var = pybamm.standard_spatial_vars
        L_y = pybamm.geometric_parameters.L_y
        L_z = pybamm.geometric_parameters.L_z
        self.variables.update({
            "y": var.y,
            "y [m]": var.y * L_y,
            "z": var.z,
            "z [m]": var.z * L_z
        })

        pybamm.citations.register("timms2020")