Esempio n. 1
0
 def test_parameters_init(self):
     with self.assertRaises(NotImplementedError):
         pybamm.Parameters(tests="not a test")
     with self.assertRaises(NotImplementedError):
         param = pybamm.Parameters(chemistry="not a chemistry")
     for chemistry in ["lead-acid"]:  # pybamm.KNOWN_CHEMISTRIES:
         param = pybamm.Parameters(chemistry=chemistry)
         self.assertEqual(param._raw["R"], 8.314)
         self.assertEqual(param._func.D_eff(param, 1, 1), 1)
Esempio n. 2
0
    def test_grad_div_1D_FV_basic(self):
        param = pybamm.Parameters()
        mesh = pybamm.Mesh(param, target_npts=50)

        y = np.ones_like(mesh.x.centres)
        N = np.ones_like(mesh.x.edges)
        yn = np.ones_like(mesh.xn.centres)
        Nn = np.ones_like(mesh.xn.edges)
        yp = np.ones_like(mesh.xp.centres)
        Np = np.ones_like(mesh.xp.edges)

        # Get all operators
        operators = pybamm.Operators("Finite Volumes", mesh)

        # Check output shape
        self.assertEqual(operators.x.grad(y).shape[0], y.shape[0] - 1)
        self.assertEqual(operators.x.div(N).shape[0], N.shape[0] - 1)
        self.assertEqual(operators.xn.grad(yn).shape[0], yn.shape[0] - 1)
        self.assertEqual(operators.xn.div(Nn).shape[0], Nn.shape[0] - 1)
        self.assertEqual(operators.xp.grad(yp).shape[0], yp.shape[0] - 1)
        self.assertEqual(operators.xp.div(Np).shape[0], Np.shape[0] - 1)

        # Check grad and div are both zero
        self.assertEqual(np.linalg.norm(operators.x.grad(y)), 0)
        self.assertEqual(np.linalg.norm(operators.x.div(N)), 0)
        self.assertEqual(np.linalg.norm(operators.xn.grad(yn)), 0)
        self.assertEqual(np.linalg.norm(operators.xn.div(Nn)), 0)
        self.assertEqual(np.linalg.norm(operators.xp.grad(yp)), 0)
        self.assertEqual(np.linalg.norm(operators.xp.div(Np)), 0)
Esempio n. 3
0
    def test_parameters_defaults_lead_acid(self):
        # Tests on how the parameters interact
        param = pybamm.Parameters(chemistry="lead-acid")
        mesh = pybamm.Mesh(param, 10)
        param.set_mesh(mesh)

        # Dimensionless lengths sum to 1
        self.assertAlmostEqual(
            param.geometric.ln + param.geometric.ls + param.geometric.lp, 1, places=10
        )
        # Diffusional C-rate should be smaller than C-rate
        self.assertLess(param.electrolyte.Cd, param.electrical.Crate)

        # # Dimensionless electrode conductivities should be large
        self.assertGreater(param.neg_electrode.iota_s, 10)
        self.assertGreater(param.pos_electrode.iota_s, 10)
        # # Dimensionless double-layer capacity should be small
        self.assertLess(param.neg_reactions.gamma_dl, 1e-3)
        self.assertLess(param.pos_reactions.gamma_dl, 1e-3)
        # # Volume change positive in negative electrode and negative in positive
        # # electrode
        self.assertGreater(param.neg_volume_changes.DeltaVsurf, 0)
        self.assertLess(param.pos_volume_changes.DeltaVsurf, 0)
        # # Excluded volume fraction should be less than 1
        self.assertLess(param.lead_acid_misc.pi_os, 1e-4)
Esempio n. 4
0
 def test_parameters_update_raw(self):
     param = pybamm.Parameters(chemistry="lead-acid")
     param.update_raw({"Ln": 0.5})
     self.assertEqual(param._raw["Ln"], 0.5)
     self.assertAlmostEqual(
         param.geometric.ln + param.geometric.ls + param.geometric.lp, 1, places=10
     )
Esempio n. 5
0
    def __init__(self,
                 model,
                 param=None,
                 mesh=None,
                 solver=None,
                 name="unnamed"):
        # Defaults
        if param is None:
            param = pybamm.Parameters()
        if mesh is None:
            mesh = pybamm.Mesh(param)
        if solver is None:
            solver = pybamm.Solver()

        # Assign attributes
        self.model = model
        self.param = param
        self.mesh = mesh
        self.solver = solver
        self.name = name

        # Initialise simulation to prepare for solving
        # Set mesh dependent parameters
        self.param.set_mesh(self.mesh)

        # Create operators from solver
        self.operators = self.solver.operators(self.mesh)

        # Assign param, operators and mesh as model attributes
        self.model.set_simulation(self.param, self.operators, self.mesh)
Esempio n. 6
0
 def setUp(self):
     self.model = pybamm.ElectrolyteCurrentModel()
     self.param = pybamm.Parameters()
     target_npts = 3
     tsteps = 10
     tend = 1
     self.mesh = pybamm.Mesh(self.param, target_npts, tsteps=tsteps, tend=tend)
     self.param.set_mesh(self.mesh)
Esempio n. 7
0
 def setUp(self):
     # Set up with a model and default simulation
     param = pybamm.Parameters()
     self.mesh = pybamm.Mesh(param)
     model = ModelForTesting(param, self.mesh)
     self.vars = pybamm.Variables(model)
     self.mesh = self.mesh
     y = np.ones_like(self.mesh.x.centres)
     self.vars.update(self.mesh.time, y)
 def setUp(self):
     self.model = pybamm.ReactionDiffusionModel()
     self.param = pybamm.Parameters()
     target_npts = 10
     tsteps = 10
     tend = 1
     self.mesh = pybamm.Mesh(self.param,
                             target_npts,
                             tsteps=tsteps,
                             tend=tend)
     self.param.set_mesh(self.mesh)
Esempio n. 9
0
    def test_parameters_options(self):
        # test dictionary input
        param = pybamm.Parameters(
            chemistry="lead-acid",
            optional_parameters={"Ln": 1 / 3, "Ls": 0.25, "Lp": 0.25},
        )
        self.assertEqual(param._raw["Ln"], 1 / 3)
        self.assertEqual(param._raw["R"], 8.314)
        self.assertAlmostEqual(
            param.geometric.ln + param.geometric.ls + param.geometric.lp, 1, places=10
        )

        # Test file input
        param = pybamm.Parameters(
            chemistry="lead-acid", optional_parameters="optional_test.csv"
        )
        self.assertEqual(param._raw["Ln"], 0.5)
        self.assertEqual(param._raw["R"], 8.314)
        self.assertAlmostEqual(
            param.geometric.ln + param.geometric.ls + param.geometric.lp, 1, places=10
        )
Esempio n. 10
0
 def test_mesh_creation(self):
     param = pybamm.Parameters()
     mesh = pybamm.Mesh(param, 50)
     self.assertEqual(mesh.x.edges[-1], 1)
     self.assertEqual(len(mesh.x.edges), len(mesh.x.centres) + 1)
     self.assertAlmostEqual(
         np.linalg.norm(
             mesh.x.centres
             - np.concatenate([mesh.xn.centres, mesh.xs.centres, mesh.xp.centres])
         ),
         0,
     )
Esempio n. 11
0
    def test_mesh_sizes(self):
        param = pybamm.Parameters()
        mesh = pybamm.Mesh(param, 50)
        self.assertEqual(mesh.nn + (mesh.ns - 2) + mesh.np, mesh.n)
        self.assertEqual(mesh.xn.npts, mesh.nn - 1)
        self.assertEqual(mesh.xs.npts, mesh.ns - 1)
        self.assertEqual(mesh.xp.npts, mesh.np - 1)
        self.assertEqual(mesh.x.npts, mesh.n - 1)

        self.assertEqual(len(mesh.xn.edges), mesh.nn)
        self.assertEqual(len(mesh.xs.edges), mesh.ns)
        self.assertEqual(len(mesh.xp.edges), mesh.np)
        self.assertEqual(len(mesh.x.edges), mesh.n)
    def test_model_convergence(self):
        """
        Exact solution: c = exp(-4*pi**2*t) * cos(2*pi*x)
        Initial conditions: c0 = cos(2*pi*x)
        Boundary conditions: Zero flux
        Source terms: 0

        Can achieve "convergence" in time by changing the integrator tolerance
        Can't get h**2 convergence in space
        """
        param = pybamm.Parameters(tests="convergence")
        param.set_mesh(self.mesh)

        def c_exact(t):
            return np.exp(-4 * np.pi**2 * t) * np.cos(
                2 * np.pi * self.mesh.x.centres)

        inits = {"concentration": c_exact(0)}

        def bcs(t):
            return {"concentration": (np.array([0]), np.array([0]))}

        def sources(t):
            return {"concentration": 0}

        tests = {"inits": inits, "bcs": bcs, "sources": sources}

        model = pybamm.ReactionDiffusionModel(tests=tests)

        ns = [1, 2, 3]
        errs = [0] * len(ns)
        for i, n in enumerate(ns):
            solver = pybamm.Solver(
                integrator="BDF",
                spatial_discretisation="Finite Volumes",
                tol=10**(-n),
            )
            sim = pybamm.Simulation(model,
                                    param=param,
                                    mesh=self.mesh,
                                    solver=solver)
            sim.run()
            errs[i] = norm(sim.vars.c.T -
                           c_exact(self.mesh.time[:, np.newaxis])) / norm(
                               c_exact(self.mesh.time[:, np.newaxis]))
        [
            self.assertLess(errs[i + 1] / errs[i], 0.14)
            for i in range(len(errs) - 1)
        ]
Esempio n. 13
0
    def test_current_conservation_finite_volumes_convergence(self):
        electrolyte = pybamm.Electrolyte()

        # Finite volume only has h**2 convergence if the mesh is uniform?
        uniform_lengths = {"Ln": 1e-3, "Ls": 1e-3, "Lp": 1e-3}
        param = pybamm.Parameters(optional_parameters=uniform_lengths,
                                  tests="convergence")

        # Test convergence
        ns = [100, 200, 400]
        errn = [0] * len(ns)
        errp = [0] * len(ns)
        for i, n in enumerate(ns):
            # Set up
            mesh = pybamm.Mesh(param, n)
            param.set_mesh(mesh)
            cn = np.cos(2 * np.pi * mesh.xcn)
            cp = np.cos(2 * np.pi * mesh.xcp)
            en = mesh.xcn**2
            ep = mesh.xcp**2
            operators = {
                "xcn": pybamm.Operators("Finite Volumes", "xcn", mesh),
                "xcp": pybamm.Operators("Finite Volumes", "xcp", mesh),
            }
            in_exact = (-2 * np.pi * np.sin(2 * np.pi * mesh.xn)) + 2 * mesh.xn
            ip_exact = (-2 * np.pi *
                        np.sin(2 * np.pi * mesh.xp / param.lp)) + 2 * mesh.xp
            current_bcs_n = (in_exact[0, None], in_exact[-1, None])
            current_bcs_p = (ip_exact[0, None], ip_exact[-1, None])

            # Exact solutions
            dendt_exact = 1 / param.gamma_dl_n * (-4 * np.pi**2 * cn + 2)
            depdt_exact = 1 / param.gamma_dl_p * (-4 * np.pi**2 * cp + 2)

            # Calculate solution and errors
            electrolyte.set_simulation(param, operators, mesh)
            dendt = electrolyte.current_conservation("xcn", cn, en, 0,
                                                     current_bcs_n)
            depdt = electrolyte.current_conservation("xcp", cp, ep, 0,
                                                     current_bcs_p)
            errn[i] = norm(
                (dendt - dendt_exact)[1:-1]) / norm(dendt_exact[1:-1])
            errp[i] = norm(
                (depdt - depdt_exact)[1:-1]) / norm(depdt_exact[1:-1])
        # Expect h**2 convergence
        for i in range(len(errn) - 1):
            self.assertLess(errn[i + 1] / errn[i], 0.26)
            self.assertLess(errp[i + 1] / errp[i], 0.26)
Esempio n. 14
0
    def test_model_shape(self):
        for spatial_discretisation in pybamm.KNOWN_SPATIAL_DISCRETISATIONS:
            # Set up
            param = pybamm.Parameters()
            mesh = pybamm.Mesh(param)
            param.set_mesh(mesh)
            operators = pybamm.Operators(spatial_discretisation, mesh)
            electrolyte = pybamm.electrolyte.StefanMaxwellDiffusion(
                param.electrolyte, operators.x, mesh.x, {})

            # Test
            c0 = electrolyte.initial_conditions()
            vars = VarsForTesting(c=c0, j=c0)
            dcdt = electrolyte.pdes_rhs(vars)

            self.assertEqual(c0.shape, dcdt.shape)
Esempio n. 15
0
 def test_functions_lead_acid(self):
     # Tests on how the parameters interact
     param = pybamm.Parameters(chemistry="lead-acid")
     mesh = pybamm.Mesh(param, 10)
     param.set_mesh(mesh)
     # Known values for dimensionless functions
     self.assertEqual(param.electrolyte.D_eff(1, 1), 1)
     self.assertEqual(param.electrolyte.kappa_eff(0, 1), 0)
     self.assertEqual(param.electrolyte.kappa_eff(1, 0), 0)
     self.assertEqual(param.neg_reactions.j0(0), 0)
     self.assertEqual(param.pos_reactions.j0(0), 0)
     # Known monotonicity for dimensionless functions
     self.assertLess(param.neg_reactions.j0(1), param.neg_reactions.j0(2))
     self.assertLess(param.pos_reactions.j0(1), param.pos_reactions.j0(2))
     self.assertGreater(param.lead_acid_misc.chi(1), param.lead_acid_misc.chi(0.5))
     self.assertLess(param.neg_reactions.U(1), param.neg_reactions.U(0.5))
     self.assertGreater(param.pos_reactions.U(1), param.pos_reactions.U(0.5))
Esempio n. 16
0
    def test_simulation_name(self):
        model = pybamm.ReactionDiffusionModel()
        param = pybamm.Parameters()
        mesh = pybamm.Mesh(param, target_npts=50)
        solver = pybamm.Solver()
        sim = pybamm.Simulation(model,
                                param=param,
                                mesh=mesh,
                                solver=solver,
                                name="test name")

        self.assertEqual(sim.param.electrolyte.s.shape,
                         sim.mesh.x.centres.shape)
        np.testing.assert_array_equal(sim.operators.x.div(mesh.x.edges),
                                      np.ones_like(mesh.x.centres))
        self.assertEqual(param, sim.model.param)
        self.assertEqual(mesh, sim.model.mesh)

        self.assertEqual(str(sim), "test name")
Esempio n. 17
0
    def test_macinnes_finite_volumes_convergence(self):
        electrolyte = pybamm.Electrolyte()

        # Finite volume only has h**2 convergence if the mesh is uniform?
        uniform_lengths = {"Ln": 1e-3, "Ls": 1e-3, "Lp": 1e-3}
        param = pybamm.Parameters(optional_parameters=uniform_lengths,
                                  tests="convergence")

        # Test convergence
        ns = [100, 200, 400]
        errn = [0] * len(ns)
        errp = [0] * len(ns)
        for i, n in enumerate(ns):
            # Set up
            mesh = pybamm.Mesh(param, n)
            param.set_mesh(mesh)
            cn = np.cos(2 * np.pi * mesh.xcn)
            cp = np.sin(2 * np.pi * mesh.xcp)
            en = mesh.xcn**2
            ep = mesh.xcp**2
            operators = {
                "xcn": pybamm.Operators("Finite Volumes", "xcn", mesh),
                "xcp": pybamm.Operators("Finite Volumes", "xcp", mesh),
            }
            in_exact = -2 * np.pi * np.sin(2 * np.pi * mesh.xn) + 2 * mesh.xn
            ip_exact = 2 * np.pi * np.cos(2 * np.pi * mesh.xp) + 2 * mesh.xp
            current_bcs_n = (in_exact[0, None], in_exact[-1, None])
            current_bcs_p = (ip_exact[0, None], ip_exact[-1, None])

            # Calculate solution and errors
            electrolyte.set_simulation(param, operators, mesh)

            i_n = electrolyte.macinnes("xcn", cn, en, current_bcs_n)
            i_p = electrolyte.macinnes("xcp", cp, ep, current_bcs_p)
            errn[i] = norm(i_n - in_exact) / norm(in_exact)
            errp[i] = norm(i_p - ip_exact) / norm(ip_exact)

        # Expect h**2 convergence
        for i in range(len(errn) - 1):
            self.assertLess(errn[i + 1] / errn[i], 0.26)
            self.assertLess(errp[i + 1] / errp[i], 0.26)
Esempio n. 18
0
    def test_finite_volumes_convergence(self):
        # Finite volume only has h**2 convergence if the mesh is uniform?
        uniform_lengths = {"Ln": 1e-3, "Ls": 1e-3, "Lp": 1e-3}
        param = pybamm.Parameters(optional_parameters=uniform_lengths,
                                  tests="convergence")

        # Test convergence
        ns = [100, 200, 400]
        errs = [0] * len(ns)
        for i, n in enumerate(ns):
            # Set up
            mesh = pybamm.Mesh(param, target_npts=n)
            param.set_mesh(mesh)
            operators = pybamm.Operators("Finite Volumes", mesh)

            # Exact solution
            c = np.cos(2 * np.pi * mesh.x.centres)
            dcdt_exact = -4 * np.pi**2 * c

            def bcs(t):
                return {"concentration": (np.array([0]), np.array([0]))}

            def sources(t):
                return {"concentration": 0}

            tests = {"bcs": bcs, "sources": sources}
            electrolyte = pybamm.electrolyte.StefanMaxwellDiffusion(
                param.electrolyte, operators.x, mesh.x, tests)

            # Calculate solution and errors
            vars = VarsForTesting(c=c)
            dcdt = electrolyte.pdes_rhs(vars)
            errs[i] = norm(dcdt - dcdt_exact) / norm(dcdt_exact)

        # Expect h**2 convergence
        [
            self.assertLess(errs[i + 1] / errs[i], 0.26)
            for i in range(len(errs) - 1)
        ]
Esempio n. 19
0
    def test_grad_div_1D_FV_convergence(self):
        # Convergence
        param = pybamm.Parameters()
        ns = [50, 100, 200]
        grad_errs = [0] * len(ns)
        div_errs = [0] * len(ns)
        for i, n in enumerate(ns):
            # Define problem and exact solutions
            mesh = pybamm.Mesh(param, target_npts=n)
            y = np.sin(mesh.x.centres)
            grad_y_exact = np.cos(mesh.x.edges[1:-1])
            div_exact = -np.sin(mesh.x.centres)

            # Get operators and flux
            operators = pybamm.operators.CartesianFiniteVolumes(mesh.x)
            grad_y_approx = operators.grad(y)

            # Calculate divergence of exact flux to avoid double errors
            # (test for those separately)
            N_exact = np.cos(mesh.x.edges)
            div_approx = operators.div(N_exact)

            # Calculate errors
            grad_errs[i] = np.linalg.norm(
                grad_y_approx - grad_y_exact
            ) / np.linalg.norm(grad_y_exact)
            div_errs[i] = np.linalg.norm(div_approx - div_exact) / np.linalg.norm(
                div_exact
            )

        # Expect h**2 convergence
        [
            self.assertLess(grad_errs[i + 1] / grad_errs[i], 0.26)
            for i in range(len(grad_errs) - 1)
        ]
        [
            self.assertLess(div_errs[i + 1] / div_errs[i], 0.26)
            for i in range(len(div_errs) - 1)
        ]
Esempio n. 20
0
    def test_variables_average_convergence(self):
        # Set up
        param = pybamm.Parameters()

        ns = [50, 100, 200]
        err = [0] * len(ns)
        errn = [0] * len(ns)
        errs = [0] * len(ns)
        errp = [0] * len(ns)
        for i, n in enumerate(ns):
            # Set up
            mesh = pybamm.Mesh(param, n)
            model = ModelForTesting(param, mesh)
            y = mesh.x.centres**2
            vars = pybamm.Variables(model)
            vars.update(mesh.time, y)
            vars.average()

            # Exact solution
            ln, ls, lp = [
                param.geometric.__dict__[l] for l in ["ln", "ls", "lp"]
            ]
            c_avg_exact = 1 / 3
            cn_avg_exact = ln**2 / 3
            cs_avg_exact = ((1 - lp)**3 - ln**3) / (3 * ls)
            cp_avg_exact = (1 - (1 - lp)**3) / (3 * lp)

            # Compare
            err[i] = norm(vars.c_avg - c_avg_exact) / norm(c_avg_exact)
            errn[i] = norm(vars.cn_avg - cn_avg_exact) / norm(cn_avg_exact)
            errs[i] = norm(vars.cs_avg - cs_avg_exact) / norm(cs_avg_exact)
            errp[i] = norm(vars.cp_avg - cp_avg_exact) / norm(cp_avg_exact)

        for i in range(len(err) - 1):
            self.assertLess(err[i + 1] / err[i], 0.26)
            self.assertLess(errn[i + 1] / errn[i], 0.26)
            self.assertLess(errs[i + 1] / errs[i], 0.26)
            self.assertLess(errp[i + 1] / errp[i], 0.26)
Esempio n. 21
0
    def test_mesh_dependent_parameters(self):
        param = pybamm.Parameters(chemistry="lead-acid")
        mesh = pybamm.Mesh(param, 10)
        param.set_mesh(mesh)

        self.assertEqual(param.electrolyte.s.shape, mesh.x.centres.shape)
Esempio n. 22
0
 def setUp(self):
     self.param = pybamm.Parameters()
     self.param_n = self.param.neg_reactions
     self.param_p = self.param.pos_reactions
     self.mesh = pybamm.Mesh(self.param, target_npts=50)