Beispiel #1
0
    def test_loqs_spm_base(self):
        t_eval = np.linspace(0, 0.01, 2)

        # SPM
        for model in [pybamm.lithium_ion.SPM(), pybamm.lead_acid.LOQS()]:
            geometry = model.default_geometry
            param = model.default_parameter_values
            param.process_model(model)
            param.process_geometry(geometry)
            mesh = pybamm.Mesh(
                geometry, model.default_submesh_types, model.default_var_pts
            )
            disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
            disc.process_model(model)
            solver = model.default_solver
            solution = solver.solve(model, t_eval)
            pybamm.QuickPlot(model, mesh, solution)

            # test quick plot of particle for spm
            if model.name == "Single Particle Model":
                output_variables = [
                    "X-averaged negative particle concentration [mol.m-3]",
                    "X-averaged positive particle concentration [mol.m-3]",
                ]
                pybamm.QuickPlot(model, mesh, solution, output_variables)
Beispiel #2
0
    def test_plot_2plus1D_spm(self):
        spm = pybamm.lithium_ion.SPM({
            "current collector": "potential pair",
            "dimensionality": 2
        })
        geometry = spm.default_geometry
        param = spm.default_parameter_values
        param.process_model(spm)
        param.process_geometry(geometry)
        var = pybamm.standard_spatial_vars
        var_pts = {
            var.x_n: 5,
            var.x_s: 5,
            var.x_p: 5,
            var.r_n: 5,
            var.r_p: 5,
            var.y: 5,
            var.z: 5,
        }
        mesh = pybamm.Mesh(geometry, spm.default_submesh_types, var_pts)
        disc_spm = pybamm.Discretisation(mesh, spm.default_spatial_methods)
        disc_spm.process_model(spm)
        t_eval = np.linspace(0, 100, 10)
        solution = spm.default_solver.solve(spm, t_eval)

        quick_plot = pybamm.QuickPlot(
            solution,
            [
                "Negative current collector potential [V]",
                "Positive current collector potential [V]",
                "Terminal voltage [V]",
            ],
        )
        quick_plot.dynamic_plot(testing=True)
        quick_plot.slider_update(1)

        # check 2D (y,z space) variables update properly for different time units
        phi_n = solution["Negative current collector potential [V]"].entries

        for unit, scale in zip(["seconds", "minutes", "hours"], [1, 60, 3600]):
            quick_plot = pybamm.QuickPlot(
                solution, ["Negative current collector potential [V]"],
                time_unit=unit)
            quick_plot.plot(0)
            qp_data = quick_plot.plots[(
                "Negative current collector potential [V]", )][0][1]
            np.testing.assert_array_almost_equal(qp_data, phi_n[:, :, 0])
            quick_plot.slider_update(t_eval[-1] / scale)
            qp_data = quick_plot.plots[(
                "Negative current collector potential [V]", )][0][1]
            np.testing.assert_array_almost_equal(qp_data, phi_n[:, :, -1])

        with self.assertRaisesRegex(NotImplementedError,
                                    "Shape not recognized for"):
            pybamm.QuickPlot(solution,
                             ["Negative particle concentration [mol.m-3]"])

        pybamm.close_plots()
Beispiel #3
0
    def test_plot_lithium_ion(self):
        spm = pybamm.lithium_ion.SPM()
        spme = pybamm.lithium_ion.SPMe()
        geometry = spm.default_geometry
        param = spm.default_parameter_values
        param.process_model(spm)
        param.process_model(spme)
        param.process_geometry(geometry)
        mesh = pybamm.Mesh(geometry, spme.default_submesh_types, spme.default_var_pts)
        disc_spm = pybamm.Discretisation(mesh, spm.default_spatial_methods)
        disc_spme = pybamm.Discretisation(mesh, spme.default_spatial_methods)
        disc_spm.process_model(spm)
        disc_spme.process_model(spme)
        t_eval = np.linspace(0, 3600, 100)
        solution_spm = spm.default_solver.solve(spm, t_eval)
        solution_spme = spme.default_solver.solve(spme, t_eval)
        quick_plot = pybamm.QuickPlot([solution_spm, solution_spme])
        quick_plot.plot(0)

        # update the axis
        new_axis = [0, 0.5, 0, 1]
        quick_plot.axis.update({("Electrolyte concentration",): new_axis})
        self.assertEqual(quick_plot.axis[("Electrolyte concentration",)], new_axis)

        # and now reset them
        quick_plot.reset_axis()
        self.assertNotEqual(quick_plot.axis[("Electrolyte concentration",)], new_axis)

        # check dynamic plot loads
        quick_plot.dynamic_plot(testing=True)

        quick_plot.update(0.01)

        # Test with different output variables
        output_vars = [
            "Negative particle surface concentration",
            "Electrolyte concentration",
            "Positive particle surface concentration",
        ]
        quick_plot = pybamm.QuickPlot(solution_spm, output_vars)
        self.assertEqual(len(quick_plot.axis), 3)
        quick_plot.plot(0)

        # update the axis
        new_axis = [0, 0.5, 0, 1]
        quick_plot.axis.update({("Electrolyte concentration",): new_axis})
        self.assertEqual(quick_plot.axis[("Electrolyte concentration",)], new_axis)

        # and now reset them
        quick_plot.reset_axis()
        self.assertNotEqual(quick_plot.axis[("Electrolyte concentration",)], new_axis)

        # check dynamic plot loads
        quick_plot.dynamic_plot(testing=True)

        quick_plot.update(0.01)
    def test_plot_1plus1D_spme(self):
        spm = pybamm.lithium_ion.SPMe(
            {"current collector": "potential pair", "dimensionality": 1}
        )
        geometry = spm.default_geometry
        param = spm.default_parameter_values
        param.process_model(spm)
        param.process_geometry(geometry)
        var = pybamm.standard_spatial_vars
        var_pts = {var.x_n: 5, var.x_s: 5, var.x_p: 5, var.r_n: 5, var.r_p: 5, var.z: 5}
        mesh = pybamm.Mesh(geometry, spm.default_submesh_types, var_pts)
        disc_spm = pybamm.Discretisation(mesh, spm.default_spatial_methods)
        disc_spm.process_model(spm)
        t_eval = np.linspace(0, 100, 10)
        solution = spm.default_solver.solve(spm, t_eval)

        # check 2D (x,z space) variables update properly for different time units
        # Note: these should be the transpose of the entries in the processed variable
        c_e = solution["Electrolyte concentration [mol.m-3]"]

        for unit, scale in zip(["seconds", "minutes", "hours"], [1, 60, 3600]):
            quick_plot = pybamm.QuickPlot(
                solution, ["Electrolyte concentration [mol.m-3]"], time_unit=unit
            )
            quick_plot.plot(0)
            qp_data = quick_plot.plots[("Electrolyte concentration [mol.m-3]",)][0][1]
            c_e_eval = c_e(t_eval[0], x=c_e.first_dim_pts, z=c_e.second_dim_pts)
            np.testing.assert_array_almost_equal(qp_data.T, c_e_eval)
            quick_plot.slider_update(t_eval[-1] / scale)
            qp_data = quick_plot.plots[("Electrolyte concentration [mol.m-3]",)][0][1]
            c_e_eval = c_e(t_eval[-1], x=c_e.first_dim_pts, z=c_e.second_dim_pts)
            np.testing.assert_array_almost_equal(qp_data.T, c_e_eval)

        pybamm.close_plots()
Beispiel #5
0
    def plot(self, quick_plot_vars=None, testing=False):
        """
        A method to quickly plot the outputs of the simulation.

        Parameters
        ----------
        quick_plot_vars: list, optional
            A list of the variables to plot.
        testing, bool, optional
            If False the plot will not be displayed
        """

        if self._solution is None:
            raise ValueError(
                "Model has not been solved, please solve the model before plotting."
            )

        if quick_plot_vars is None:
            quick_plot_vars = self.quick_plot_vars

        plot = pybamm.QuickPlot(self._solution,
                                output_variables=quick_plot_vars)

        if isnotebook():
            import ipywidgets as widgets

            widgets.interact(
                plot.plot,
                t=widgets.FloatSlider(min=0,
                                      max=plot.max_t,
                                      step=0.05,
                                      value=0),
            )
        else:
            plot.dynamic_plot(testing=testing)
Beispiel #6
0
 def test_model_with_inputs(self):
     chemistry = pybamm.parameter_sets.Chen2020
     parameter_values = pybamm.ParameterValues(chemistry=chemistry)
     model = pybamm.lithium_ion.SPMe()
     parameter_values.update({"Electrode height [m]": "[input]"})
     solver = pybamm.CasadiSolver(mode="safe")
     sim1 = pybamm.Simulation(model,
                              parameter_values=parameter_values,
                              solver=solver)
     inputs1 = {"Electrode height [m]": 1.00}
     sol1 = sim1.solve(t_eval=np.linspace(0, 1000, 101), inputs=inputs1)
     sim2 = pybamm.Simulation(model,
                              parameter_values=parameter_values,
                              solver=solver)
     inputs2 = {"Electrode height [m]": 2.00}
     sol2 = sim2.solve(t_eval=np.linspace(0, 1000, 101), inputs=inputs2)
     output_variables = [
         "Terminal voltage [V]",
         "Current [A]",
         "Negative electrode potential [V]",
         "Positive electrode potential [V]",
         "Electrolyte potential [V]",
         "Electrolyte concentration",
         "Negative particle surface concentration",
         "Positive particle surface concentration",
     ]
     quick_plot = pybamm.QuickPlot(solutions=[sol1, sol2],
                                   output_variables=output_variables)
     quick_plot.dynamic_plot(testing=True)
     quick_plot.slider_update(1)
     pybamm.close_plots()
    def setUp(self):
        self.model = pybamm.lithium_ion.DFN()
        self.parameter_values = self.model.default_parameter_values
        self.sim = pybamm.Simulation(
            self.model,
            parameter_values=self.parameter_values
        )
        self.sim.solve([0, 3700])
        self.solution = self.sim.solution

        self.t = self.solution["Time [s]"]
        self.final_time = int(self.t.entries[len(self.t.entries) - 1])
        self.time_array = np.linspace(0, self.final_time, num=3)

        self.images = []
        self.image_files = []
        for val in self.time_array:
            self.plot = pybamm.QuickPlot(self.sim, time_unit="seconds")
            self.plot.plot(val)
            self.images.append("plot" + str(val) + ".png")
            self.plot.fig.savefig("plot" + str(val) + ".png", dpi=200)
            plt.close()

        for image in self.images:
            self.image_files.append(imageio.imread(image))
        imageio.mimsave('plot.gif', self.image_files, duration=0.1)

        for image in self.images:
            os.remove(image)
Beispiel #8
0
    def test_plot_2plus1D_spm(self):
        spm = pybamm.lithium_ion.SPM({
            "current collector": "potential pair",
            "dimensionality": 2
        })
        geometry = spm.default_geometry
        param = spm.default_parameter_values
        param.process_model(spm)
        param.process_geometry(geometry)
        var = pybamm.standard_spatial_vars
        var_pts = {
            var.x_n: 5,
            var.x_s: 5,
            var.x_p: 5,
            var.r_n: 5,
            var.r_p: 5,
            var.y: 5,
            var.z: 5,
        }
        mesh = pybamm.Mesh(geometry, spm.default_submesh_types, var_pts)
        disc_spm = pybamm.Discretisation(mesh, spm.default_spatial_methods)
        disc_spm.process_model(spm)
        t_eval = np.linspace(0, 3600, 100)
        solution_spm = spm.default_solver.solve(spm, t_eval)

        quick_plot = pybamm.QuickPlot(
            solution_spm,
            [
                "Negative current collector potential [V]",
                "Positive current collector potential [V]",
                "Terminal voltage [V]",
            ],
        )
        quick_plot.dynamic_plot(testing=True)
        quick_plot.slider_update(1)

        with self.assertRaisesRegex(NotImplementedError,
                                    "Shape not recognized for"):
            pybamm.QuickPlot(
                solution_spm,
                ["Negative particle concentration [mol.m-3]"],
            )
Beispiel #9
0
 def test_failure(self):
     with self.assertRaisesRegex(TypeError, "'models' must be"):
         pybamm.QuickPlot(1, None, None)
     with self.assertRaisesRegex(TypeError, "'meshes' must be"):
         model = pybamm.lithium_ion.SPM()
         pybamm.QuickPlot(model, 1, None)
     with self.assertRaisesRegex(TypeError, "'solutions' must be"):
         geometry = model.default_geometry
         param = model.default_parameter_values
         param.process_model(model)
         param.process_geometry(geometry)
         mesh = pybamm.Mesh(
             geometry, model.default_submesh_types, model.default_var_pts
         )
         pybamm.QuickPlot(model, mesh, 1)
     with self.assertRaisesRegex(ValueError, "must provide the same"):
         pybamm.QuickPlot(
             model,
             mesh,
             [pybamm.Solution(0, 0, 0, 0, ""), pybamm.Solution(0, 0, 0, 0, "")],
         )
Beispiel #10
0
    def test_spm_simulation(self):
        # SPM
        model = pybamm.lithium_ion.SPM()
        sim = pybamm.Simulation(model)

        t_eval = np.linspace(0, 10, 2)
        sim.solve(t_eval)

        # mixed simulation and solution input
        # solution should be extracted from the simulation
        quick_plot = pybamm.QuickPlot([sim, sim.solution])
        quick_plot.plot(0)
Beispiel #11
0
    def test_plot_lead_acid(self):
        loqs = pybamm.lead_acid.LOQS()
        geometry = loqs.default_geometry
        param = loqs.default_parameter_values
        param.process_model(loqs)
        param.process_geometry(geometry)
        mesh = pybamm.Mesh(geometry, loqs.default_submesh_types, loqs.default_var_pts)
        disc_loqs = pybamm.Discretisation(mesh, loqs.default_spatial_methods)
        disc_loqs.process_model(loqs)
        t_eval = np.linspace(0, 3600, 100)
        solution_loqs = loqs.default_solver.solve(loqs, t_eval)

        pybamm.QuickPlot(solution_loqs)
Beispiel #12
0
def dynamic_plot(*args, **kwargs):
    """
    Creates a :class:`pybamm.QuickPlot` object (with arguments 'args' and keyword
    arguments 'kwargs') and then calls :meth:`pybamm.QuickPlot.dynamic_plot`.
    The key-word argument 'testing' is passed to the 'dynamic_plot' method, not the
    `QuickPlot` class.

    Returns
    -------
    plot : :class:`pybamm.QuickPlot`
        The 'QuickPlot' object that was created
    """
    kwargs_for_class = {k: v for k, v in kwargs.items() if k != "testing"}
    plot = pybamm.QuickPlot(*args, **kwargs_for_class)
    plot.dynamic_plot(kwargs.get("testing", False))
    return plot
Beispiel #13
0
def plot_graph(solution, sim, t=None, reply=False, comparing=False):

    if t == None and not comparing:
        t = solution["Time [s]"]
    final_time = int(t.entries[len(t.entries) - 1])
    # plot_type = random.randint(0, 1)
    time = random.randint(0, final_time)
    print(time)
    # if plot_type == 0:
    plot = pybamm.QuickPlot(sim, time_unit="seconds")
    plot.plot(time)
    if not reply:
        plot.fig.savefig("foo.png", dpi=300)
    elif reply:
        plot.fig.savefig("replyFoo.png", dpi=300)

    # if comparing:
    #     print(solution[0])
    #     t = solution[0]["Time [s]"]
    #     final_time = int(t.entries[len(t.entries) - 1])
    #     time = random.randint(0, final_time)
    #     plot = pybamm.QuickPlot(sim)
    #     plot.plot(time)
    #     plot.fig.savefig("foo.png", dpi=300)

    
    # Below was the code to plot random output variables (not needed right now)
    # else:
    #     while True:
    #         lower_limit = random.randint(0, len(output_variables))
    #         upper_limit = random.randint(0, len(output_variables))
    #         if upper_limit - lower_limit < 9 and upper_limit - lower_limit > 2:
    #             plot = pybamm.QuickPlot(
    #                 sim,
    #                 output_variables=output_variables[lower_limit:upper_limit],
    #                 time_unit="seconds",
    #             )
    #             plot.plot(time)
    #             if not reply:
    #                 plot.fig.savefig("foo.png", dpi=300)
    #             elif reply:
    #                 plot.fig.savefig("replyFoo.png", dpi=300)
    #             # foo1.pdf_to_png('foo.pdf')
    #             break

    return time
Beispiel #14
0
    def test_loqs_spme(self):
        t_eval = np.linspace(0, 10, 2)

        for model in [pybamm.lithium_ion.SPMe(), pybamm.lead_acid.LOQS()]:
            geometry = model.default_geometry
            param = model.default_parameter_values
            param.process_model(model)
            param.process_geometry(geometry)
            var = pybamm.standard_spatial_vars
            var_pts = {
                var.x_n: 5,
                var.x_s: 5,
                var.x_p: 5,
                var.r_n: 5,
                var.r_p: 5
            }
            mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts)
            disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
            disc.process_model(model)
            solver = model.default_solver
            solution = solver.solve(model, t_eval)
            pybamm.QuickPlot(solution)

            # check 1D (space) variables update properly for different time units
            t = solution["Time [s]"].entries
            c_e_var = solution["Electrolyte concentration [mol.m-3]"]
            # 1D variables should be evaluated on edges
            L_x = param.evaluate(model.param.L_x)
            c_e = c_e_var(t=t,
                          x=mesh.combine_submeshes(*c_e_var.domain).edges *
                          L_x)

            for unit, scale in zip(["seconds", "minutes", "hours"],
                                   [1, 60, 3600]):
                quick_plot = pybamm.QuickPlot(
                    solution, ["Electrolyte concentration [mol.m-3]"],
                    time_unit=unit)
                quick_plot.plot(0)

                qp_data = (
                    quick_plot.plots[("Electrolyte concentration [mol.m-3]",
                                      )][0][0].get_ydata(), )[0]
                np.testing.assert_array_almost_equal(qp_data, c_e[:, 0])
                quick_plot.slider_update(t_eval[-1] / scale)

                qp_data = (
                    quick_plot.plots[("Electrolyte concentration [mol.m-3]",
                                      )][0][0].get_ydata(), )[0][:, 0]
                np.testing.assert_array_almost_equal(qp_data, c_e[:, 1])

            # test quick plot of particle for spme
            if model.name == "Single Particle Model with electrolyte":
                output_variables = [
                    "X-averaged negative particle concentration [mol.m-3]",
                    "X-averaged positive particle concentration [mol.m-3]",
                    "Negative particle concentration [mol.m-3]",
                    "Positive particle concentration [mol.m-3]",
                ]
                pybamm.QuickPlot(solution, output_variables)

                # check 2D (space) variables update properly for different time units
                c_n = solution["Negative particle concentration [mol.m-3]"]

                for unit, scale in zip(["seconds", "minutes", "hours"],
                                       [1, 60, 3600]):
                    quick_plot = pybamm.QuickPlot(
                        solution,
                        ["Negative particle concentration [mol.m-3]"],
                        time_unit=unit,
                    )
                    quick_plot.plot(0)
                    qp_data = quick_plot.plots[(
                        "Negative particle concentration [mol.m-3]", )][0][1]
                    c_n_eval = c_n(t_eval[0],
                                   r=c_n.first_dim_pts,
                                   x=c_n.second_dim_pts)
                    np.testing.assert_array_almost_equal(qp_data, c_n_eval)
                    quick_plot.slider_update(t_eval[-1] / scale)
                    qp_data = quick_plot.plots[(
                        "Negative particle concentration [mol.m-3]", )][0][1]
                    c_n_eval = c_n(t_eval[-1],
                                   r=c_n.first_dim_pts,
                                   x=c_n.second_dim_pts)
                    np.testing.assert_array_almost_equal(qp_data, c_n_eval)

        pybamm.close_plots()
Beispiel #15
0
    "Positive electrode potential [V]": comsol_phi_p,
    "Terminal voltage [V]": comsol_voltage,
    # Add spatial variables for use in QuickPlot
    "x": pybamm_model.variables["x"],
    "x [m]": pybamm_model.variables["x [m]"],
}

# Make new solution with same t and y
comsol_solution = pybamm.Solution(pybamm_solution.t, pybamm_solution.y)
# Update model timescale to match the pybamm model
comsol_model.timescale = pybamm_model.timescale
comsol_solution.model = comsol_model

# plot
output_variables = [
    "Negative particle surface concentration [mol.m-3]",
    "Electrolyte concentration [mol.m-3]",
    "Positive particle surface concentration [mol.m-3]",
    "Current [A]",
    "Negative electrode potential [V]",
    "Electrolyte potential [V]",
    "Positive electrode potential [V]",
    "Terminal voltage [V]",
]
plot = pybamm.QuickPlot(
    [pybamm_solution, comsol_solution],
    output_variables=output_variables,
    labels=["PyBaMM", "Comsol"],
)
plot.dynamic_plot()
Beispiel #16
0
    def test_simple_ode_model(self):
        model = pybamm.BaseBatteryModel(name="Simple ODE Model")

        whole_cell = ["negative electrode", "separator", "positive electrode"]
        # Create variables: domain is explicitly empty since these variables are only
        # functions of time
        a = pybamm.Variable("a", domain=[])
        b = pybamm.Variable("b", domain=[])
        c = pybamm.Variable("c", domain=[])

        # Simple ODEs
        model.rhs = {a: pybamm.Scalar(2), b: pybamm.Scalar(0), c: -c}

        # Simple initial conditions
        model.initial_conditions = {
            a: pybamm.Scalar(0),
            b: pybamm.Scalar(1),
            c: pybamm.Scalar(1),
        }
        # no boundary conditions for an ODE model
        # Broadcast some of the variables
        model.variables = {
            "a": a,
            "b broadcasted": pybamm.FullBroadcast(b, whole_cell, "current collector"),
            "c broadcasted": pybamm.FullBroadcast(
                c, ["negative electrode", "separator"], "current collector"
            ),
        }

        # ODEs only (don't use jacobian)
        model.use_jacobian = False

        # Process and solve
        geometry = model.default_geometry
        param = model.default_parameter_values
        param.process_model(model)
        param.process_geometry(geometry)
        mesh = pybamm.Mesh(geometry, model.default_submesh_types, model.default_var_pts)
        disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
        disc.process_model(model)
        solver = model.default_solver
        t_eval = np.linspace(0, 2, 100)
        solution = solver.solve(model, t_eval)
        quick_plot = pybamm.QuickPlot(model, mesh, solution)
        quick_plot.plot(0)

        # update the axis
        new_axis = [0, 0.5, 0, 1]
        quick_plot.axis.update({("a",): new_axis})
        self.assertEqual(quick_plot.axis[("a",)], new_axis)

        # and now reset them
        quick_plot.reset_axis()
        self.assertNotEqual(quick_plot.axis[("a",)], new_axis)

        # check dynamic plot loads
        quick_plot.dynamic_plot(testing=True)

        quick_plot.update(0.01)

        # Test with different output variables
        quick_plot = pybamm.QuickPlot(model, mesh, solution, ["b broadcasted"])
        self.assertEqual(len(quick_plot.axis), 1)
        quick_plot.plot(0)

        quick_plot = pybamm.QuickPlot(
            model,
            mesh,
            solution,
            [["a", "a"], ["b broadcasted", "b broadcasted"], "c broadcasted"],
        )
        self.assertEqual(len(quick_plot.axis), 3)
        quick_plot.plot(0)

        # update the axis
        new_axis = [0, 0.5, 0, 1]
        var_key = ("c broadcasted",)
        quick_plot.axis.update({var_key: new_axis})
        self.assertEqual(quick_plot.axis[var_key], new_axis)

        # and now reset them
        quick_plot.reset_axis()
        self.assertNotEqual(quick_plot.axis[var_key], new_axis)

        # check dynamic plot loads
        quick_plot.dynamic_plot(testing=True)

        quick_plot.update(0.01)

        # Test longer name
        model.variables["Variable with a very long name"] = model.variables["a"]
        quick_plot = pybamm.QuickPlot(model, mesh, solution)
        quick_plot.plot(0)

        # Test errors
        with self.assertRaisesRegex(ValueError, "mismatching variable domains"):
            pybamm.QuickPlot(model, mesh, solution, [["a", "b broadcasted"]])
        model.variables["3D variable"] = disc.process_symbol(
            pybamm.Broadcast(1, ["negative particle"])
        )
        with self.assertRaisesRegex(NotImplementedError, "cannot plot 3D variables"):
            pybamm.QuickPlot(model, mesh, solution, ["3D variable"])
def ambient_temperature(t):
    return 300 + t * 100 / 3600


param = model.default_parameter_values
param.update({"Ambient temperature [K]": ambient_temperature},
             check_already_exists=False)
param.process_model(model)
param.process_geometry(geometry)

# set mesh
var = pybamm.standard_spatial_vars
var_pts = {var.x_n: 30, var.x_s: 30, var.x_p: 30, var.r_n: 10, var.r_p: 10}
mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts)

# discretise model
disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
disc.process_model(model)

# solve model
t_eval = np.linspace(0, 3600 / 2, 100)
solver = pybamm.CasadiSolver(mode="fast")
solver.rtol = 1e-3
solver.atol = 1e-6
solution = solver.solve(model, t_eval)

# plot
plot = pybamm.QuickPlot(
    solution, ["X-averaged cell temperature [K]", "Ambient temperature [K]"])
plot.dynamic_plot()
Beispiel #18
0
        fill_value="extrapolate",
        bounds_error=False,
    ),
    pybamm.t,
)
comsol_voltage.mesh = None
comsol_voltage.secondary_mesh = None

# Create comsol model with dictionary of Matrix variables
comsol_model = pybamm.BaseModel()
comsol_model.variables = {
    "Negative particle surface concentration [mol.m-3]": comsol_c_n_surf,
    "Electrolyte concentration [mol.m-3]": comsol_c_e,
    "Positive particle surface concentration [mol.m-3]": comsol_c_p_surf,
    "Current [A]": pybamm_model.variables["Current [A]"],
    "Negative electrode potential [V]": comsol_phi_n,
    "Electrolyte potential [V]": comsol_phi_e,
    "Positive electrode potential [V]": comsol_phi_p,
    "Terminal voltage [V]": comsol_voltage,
}
# Make new solution with same t and y
comsol_solution = pybamm.Solution(pybamm_solution.t, pybamm_solution.y)
comsol_solution.model = comsol_model
# plot
plot = pybamm.QuickPlot(
    [pybamm_solution, comsol_solution],
    output_variables=comsol_model.variables.keys(),
    labels=["PyBaMM", "Comsol"],
)
plot.dynamic_plot()
Beispiel #19
0
# load parameter values and process models and geometry
param = models[0].default_parameter_values
param["Current function [A]"] = 1

for model in models:
    param.process_model(model)

# set mesh
var = pybamm.standard_spatial_vars
var_pts = {var.x_n: 10, var.x_s: 10, var.x_p: 10, var.r_n: 5, var.r_p: 5}

# discretise models
for model in models:
    # create geometry
    geometry = model.default_geometry
    param.process_geometry(geometry)
    mesh = pybamm.Mesh(geometry, models[-1].default_submesh_types, var_pts)
    disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
    disc.process_model(model)

# solve model
solutions = [None] * len(models)
t_eval = np.linspace(0, 3600, 100)
for i, model in enumerate(models):
    solutions[i] = model.default_solver.solve(model, t_eval)

# plot
plot = pybamm.QuickPlot(solutions, linestyles=[":", "--", "-"])
plot.dynamic_plot()
# process geometry and discretise models
for model in models:
    geometry = model.default_geometry
    param.process_geometry(geometry)
    var = pybamm.standard_spatial_vars
    var_pts = {
        var.x_n: 5,
        var.x_s: 5,
        var.x_p: 5,
        var.r_n: 5,
        var.r_p: 5,
        var.y: 5,
        var.z: 5,
    }
    mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts)
    disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
    disc.process_model(model)

# solve model
solutions = [None] * len(models)
t_eval = np.linspace(0, 1, 1000)
for i, model in enumerate(models):
    solution = model.default_solver.solve(model, t_eval)
    solutions[i] = solution

# plot
# TO DO: plotting 3D variables
output_variables = ["Terminal voltage [V]"]
plot = pybamm.QuickPlot(models, mesh, solutions, output_variables)
plot.dynamic_plot()
    return grading * R_p_0


params[1]["Negative particle radius [m]"] = negative_radius
params[1]["Positive particle radius [m]"] = positive_radius

# set up and solve simulations
t_eval = np.linspace(0, 3600, 100)
sols = []
for model, param in zip(models, params):
    sim = pybamm.Simulation(model, parameter_values=param)
    sol = sim.solve(t_eval)
    sols.append(sol)

output_variables = [
    "Negative particle surface concentration",
    "Electrolyte concentration",
    "Positive particle surface concentration",
    "Current [A]",
    "Negative electrode potential [V]",
    "Electrolyte potential [V]",
    "Positive electrode potential [V]",
    "Terminal voltage [V]",
    "Negative particle radius",
    "Positive particle radius",
]

# plot
plot = pybamm.QuickPlot(sols, output_variables=output_variables)
plot.dynamic_plot()
Beispiel #22
0
    param.process_geometry(geometry)
    var = pybamm.standard_spatial_vars
    var_pts = {
        var.x_n: 10,
        var.x_s: 10,
        var.x_p: 10,
        var.r_n: 10,
        var.r_p: 10,
        var.y: 10,
        var.z: 10,
    }
    mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts)
    disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
    disc.process_model(model)

# solve model
solutions = [None] * len(models)
t_eval = np.linspace(0, 3600, 1000)
for i, model in enumerate(models):
    solution = model.default_solver.solve(model, t_eval)
    solutions[i] = solution

# plot
output_variables = [
    "Terminal voltage [V]",
    "Negative current collector potential [V]",
    "Positive current collector potential [V]",
]
plot = pybamm.QuickPlot(solutions, output_variables)
plot.dynamic_plot()
Beispiel #23
0
var = pybamm.standard_spatial_vars
var_pts = {var.x_n: 30, var.x_s: 30, var.x_p: 30, var.r_n: 10, var.r_p: 10}
mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts)

# discretise model
disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
disc.process_model(model)

# solve model
t_eval = np.linspace(0, 3600, 100)
solver = pybamm.CasadiSolver(mode="fast", atol=1e-6, rtol=1e-3)
solution = solver.solve(model, t_eval)

# plot
plot = pybamm.QuickPlot(
    solution,
    [
        "Negative particle concentration [mol.m-3]",
        "Electrolyte concentration [mol.m-3]",
        "Positive particle concentration [mol.m-3]",
        "Current [A]",
        "Negative electrode potential [V]",
        "Electrolyte potential [V]",
        "Positive electrode potential [V]",
        "Terminal voltage [V]",
    ],
    time_unit="seconds",
    spatial_unit="um",
)
plot.dynamic_plot()
Beispiel #24
0
    def test_simple_ode_model(self):
        model = pybamm.BaseBatteryModel(name="Simple ODE Model")

        whole_cell = ["negative electrode", "separator", "positive electrode"]
        # Create variables: domain is explicitly empty since these variables are only
        # functions of time
        a = pybamm.Variable("a", domain=[])
        b = pybamm.Variable("b", domain=[])
        c = pybamm.Variable("c", domain=[])

        # Simple ODEs
        model.rhs = {a: pybamm.Scalar(2), b: pybamm.Scalar(0), c: -c}

        # Simple initial conditions
        model.initial_conditions = {
            a: pybamm.Scalar(0),
            b: pybamm.Scalar(1),
            c: pybamm.Scalar(1),
        }
        # no boundary conditions for an ODE model
        # Broadcast some of the variables
        model.variables = {
            "a":
            a,
            "b broadcasted":
            pybamm.FullBroadcast(b, whole_cell, "current collector"),
            "c broadcasted":
            pybamm.FullBroadcast(c, ["negative electrode", "separator"],
                                 "current collector"),
            "b broadcasted negative electrode":
            pybamm.PrimaryBroadcast(b, "negative particle"),
            "c broadcasted positive electrode":
            pybamm.PrimaryBroadcast(c, "positive particle"),
            "x [m]":
            pybamm.standard_spatial_vars.x,
            "x":
            pybamm.standard_spatial_vars.x,
            "r_n [m]":
            pybamm.standard_spatial_vars.r_n,
            "r_n":
            pybamm.standard_spatial_vars.r_n,
            "r_p [m]":
            pybamm.standard_spatial_vars.r_p,
            "r_p":
            pybamm.standard_spatial_vars.r_p,
        }

        # ODEs only (don't use jacobian)
        model.use_jacobian = False

        # Process and solve
        geometry = model.default_geometry
        param = model.default_parameter_values
        param.process_model(model)
        param.process_geometry(geometry)
        mesh = pybamm.Mesh(geometry, model.default_submesh_types,
                           model.default_var_pts)
        disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
        disc.process_model(model)
        solver = model.default_solver
        t_eval = np.linspace(0, 2, 100)
        solution = solver.solve(model, t_eval)
        quick_plot = pybamm.QuickPlot(
            solution,
            [
                "a",
                "b broadcasted",
                "c broadcasted",
                "b broadcasted negative electrode",
                "c broadcasted positive electrode",
            ],
        )
        quick_plot.plot(0)

        # update the axis
        new_axis = [0, 0.5, 0, 1]
        quick_plot.axis_limits.update({("a", ): new_axis})
        self.assertEqual(quick_plot.axis_limits[("a", )], new_axis)

        # and now reset them
        quick_plot.reset_axis()
        self.assertNotEqual(quick_plot.axis_limits[("a", )], new_axis)

        # check dynamic plot loads
        quick_plot.dynamic_plot(testing=True)

        quick_plot.slider_update(0.01)

        # Test with different output variables
        quick_plot = pybamm.QuickPlot(solution, ["b broadcasted"])
        self.assertEqual(len(quick_plot.axis_limits), 1)
        quick_plot.plot(0)

        quick_plot = pybamm.QuickPlot(
            solution,
            [
                ["a", "a"],
                ["b broadcasted", "b broadcasted"],
                "c broadcasted",
                "b broadcasted negative electrode",
                "c broadcasted positive electrode",
            ],
        )
        self.assertEqual(len(quick_plot.axis_limits), 5)
        quick_plot.plot(0)

        # update the axis
        new_axis = [0, 0.5, 0, 1]
        var_key = ("c broadcasted", )
        quick_plot.axis_limits.update({var_key: new_axis})
        self.assertEqual(quick_plot.axis_limits[var_key], new_axis)

        # and now reset them
        quick_plot.reset_axis()
        self.assertNotEqual(quick_plot.axis_limits[var_key], new_axis)

        # check dynamic plot loads
        quick_plot.dynamic_plot(testing=True)

        quick_plot.slider_update(0.01)

        # Test longer name
        model.variables["Variable with a very long name"] = model.variables[
            "a"]
        quick_plot = pybamm.QuickPlot(solution,
                                      ["Variable with a very long name"])
        quick_plot.plot(0)

        # Test different inputs
        quick_plot = pybamm.QuickPlot(
            [solution, solution],
            ["a"],
            colors=["r", "g", "b"],
            linestyles=["-", "--"],
            figsize=(1, 2),
            labels=["sol 1", "sol 2"],
        )
        self.assertEqual(quick_plot.colors, ["r", "g", "b"])
        self.assertEqual(quick_plot.linestyles, ["-", "--"])
        self.assertEqual(quick_plot.figsize, (1, 2))
        self.assertEqual(quick_plot.labels, ["sol 1", "sol 2"])

        # Test different time units
        quick_plot = pybamm.QuickPlot(solution, ["a"])
        self.assertEqual(quick_plot.time_scaling_factor, 1)
        quick_plot = pybamm.QuickPlot(solution, ["a"], time_unit="seconds")
        quick_plot.plot(0)
        self.assertEqual(quick_plot.time_scaling_factor, 1)
        np.testing.assert_array_almost_equal(
            quick_plot.plots[("a", )][0][0].get_xdata(), t_eval)
        np.testing.assert_array_almost_equal(
            quick_plot.plots[("a", )][0][0].get_ydata(), 2 * t_eval)
        quick_plot = pybamm.QuickPlot(solution, ["a"], time_unit="minutes")
        quick_plot.plot(0)
        self.assertEqual(quick_plot.time_scaling_factor, 60)
        np.testing.assert_array_almost_equal(
            quick_plot.plots[("a", )][0][0].get_xdata(), t_eval / 60)
        np.testing.assert_array_almost_equal(
            quick_plot.plots[("a", )][0][0].get_ydata(), 2 * t_eval)
        quick_plot = pybamm.QuickPlot(solution, ["a"], time_unit="hours")
        quick_plot.plot(0)
        self.assertEqual(quick_plot.time_scaling_factor, 3600)
        np.testing.assert_array_almost_equal(
            quick_plot.plots[("a", )][0][0].get_xdata(), t_eval / 3600)
        np.testing.assert_array_almost_equal(
            quick_plot.plots[("a", )][0][0].get_ydata(), 2 * t_eval)
        with self.assertRaisesRegex(ValueError, "time unit"):
            pybamm.QuickPlot(solution, ["a"], time_unit="bad unit")
        # long solution defaults to hours instead of seconds
        solution_long = solver.solve(model, np.linspace(0, 1e5))
        quick_plot = pybamm.QuickPlot(solution_long, ["a"])
        self.assertEqual(quick_plot.time_scaling_factor, 3600)

        # Test different spatial units
        quick_plot = pybamm.QuickPlot(solution, ["a"])
        self.assertEqual(quick_plot.spatial_unit, "$\mu m$")
        quick_plot = pybamm.QuickPlot(solution, ["a"], spatial_unit="m")
        self.assertEqual(quick_plot.spatial_unit, "m")
        quick_plot = pybamm.QuickPlot(solution, ["a"], spatial_unit="mm")
        self.assertEqual(quick_plot.spatial_unit, "mm")
        quick_plot = pybamm.QuickPlot(solution, ["a"], spatial_unit="um")
        self.assertEqual(quick_plot.spatial_unit, "$\mu m$")
        with self.assertRaisesRegex(ValueError, "spatial unit"):
            pybamm.QuickPlot(solution, ["a"], spatial_unit="bad unit")

        # Test 2D variables
        model.variables["2D variable"] = disc.process_symbol(
            pybamm.FullBroadcast(1, "negative particle",
                                 {"secondary": "negative electrode"}))
        quick_plot = pybamm.QuickPlot(solution, ["2D variable"])
        quick_plot.plot(0)
        quick_plot.dynamic_plot(testing=True)
        quick_plot.slider_update(0.01)

        with self.assertRaisesRegex(NotImplementedError,
                                    "Cannot plot 2D variables"):
            pybamm.QuickPlot([solution, solution], ["2D variable"])

        # Test different variable limits
        quick_plot = pybamm.QuickPlot(
            solution, ["a", ["c broadcasted", "c broadcasted"]],
            variable_limits="tight")
        self.assertEqual(quick_plot.axis_limits[("a", )][2:], [None, None])
        self.assertEqual(
            quick_plot.axis_limits[("c broadcasted", "c broadcasted")][2:],
            [None, None])
        quick_plot.plot(0)
        quick_plot.slider_update(1)

        quick_plot = pybamm.QuickPlot(solution, ["2D variable"],
                                      variable_limits="tight")
        self.assertEqual(quick_plot.variable_limits[("2D variable", )],
                         (None, None))
        quick_plot.plot(0)
        quick_plot.slider_update(1)

        quick_plot = pybamm.QuickPlot(
            solution,
            ["a", ["c broadcasted", "c broadcasted"]],
            variable_limits={
                "a": [1, 2],
                ("c broadcasted", "c broadcasted"): [3, 4]
            },
        )
        self.assertEqual(quick_plot.axis_limits[("a", )][2:], [1, 2])
        self.assertEqual(
            quick_plot.axis_limits[("c broadcasted", "c broadcasted")][2:],
            [3, 4])
        quick_plot.plot(0)
        quick_plot.slider_update(1)

        quick_plot = pybamm.QuickPlot(solution, ["a", "b broadcasted"],
                                      variable_limits={"a": "tight"})
        self.assertEqual(quick_plot.axis_limits[("a", )][2:], [None, None])
        self.assertNotEqual(quick_plot.axis_limits[("b broadcasted", )][2:],
                            [None, None])
        quick_plot.plot(0)
        quick_plot.slider_update(1)

        with self.assertRaisesRegex(
                TypeError,
                "variable_limits must be 'fixed', 'tight', or a dict"):
            pybamm.QuickPlot(solution, ["a", "b broadcasted"],
                             variable_limits="bad variable limits")

        # Test errors
        with self.assertRaisesRegex(ValueError,
                                    "Mismatching variable domains"):
            pybamm.QuickPlot(solution, [["a", "b broadcasted"]])
        with self.assertRaisesRegex(ValueError, "labels"):
            pybamm.QuickPlot([solution, solution], ["a"],
                             labels=["sol 1", "sol 2", "sol 3"])

        # Remove 'x [m]' from the variables and make sure a key error is raise
        del solution.model.variables["x [m]"]
        with self.assertRaisesRegex(
                KeyError, "Can't find spatial scale for 'negative electrode'"):
            pybamm.QuickPlot(solution, ["b broadcasted"])

        # No variable can be NaN
        model.variables["NaN variable"] = disc.process_symbol(
            pybamm.Scalar(np.nan))
        with self.assertRaisesRegex(
                ValueError, "All-NaN variable 'NaN variable' provided"):
            pybamm.QuickPlot(solution, ["NaN variable"])
Beispiel #25
0
 def test_failure(self):
     with self.assertRaisesRegex(TypeError, "solutions must be"):
         pybamm.QuickPlot(1)
Beispiel #26
0
def US06_experiment(reply=False):
    model = pybamm.lithium_ion.DFN()
    # import drive cycle from file
    if reply: 
        drive_cycle = pd.read_csv("drive_cycle.csv", comment="#", header=None).to_numpy()
    elif not reply:
        drive_cycle = pd.read_csv("US06.csv", comment="#", header=None).to_numpy()
    # create interpolant
    param = model.default_parameter_values
    timescale = param.evaluate(model.timescale)
    current_interpolant = pybamm.Interpolant(
        drive_cycle[:, 0], drive_cycle[:, 1], timescale * pybamm.t
    )
    # set drive cycle
    param["Current function [A]"] = current_interpolant

    sim_US06_1 = pybamm.Simulation(
        model, parameter_values=param, solver=pybamm.CasadiSolver(mode="fast")
    )
    sol_US06_1 = sim_US06_1.solve()

    if reply:
        time = foo1.plot_graph(sol_US06_1, sim_US06_1, reply=reply)
        return time

    solved = False
    print("REACHED")
    while not solved:
        try:
            cycle = US06_experiment_cycle()
            # cycle = ["Charge at 1 A until 4.1 V", "Hold at 4.1 V until 50 mA"]

            experiment = pybamm.Experiment(cycle)
            sim_cccv = pybamm.Simulation(model, experiment=experiment)
            sol_cccv = sim_cccv.solve()
            new_model = model.set_initial_conditions_from(sol_cccv, inplace=False)
            sim_US06_2 = pybamm.Simulation(
                new_model,
                parameter_values=param,
                solver=pybamm.CasadiSolver(mode="fast"),
            )
            sol_US06_2 = sim_US06_2.solve()
            # pybamm.dynamic_plot(
            #     [sol_US06_1, sol_US06_2],
            #     labels=["Default initial conditions", "Fully charged"],
            # )
            solution = [sol_US06_1, sol_US06_2]
            sim = [sim_US06_1, sim_US06_2]
            t = solution[0]["Time [s]"]
            final_time = int(t.entries[len(t.entries) - 1])
            time = random.randint(0, final_time)
            plot = pybamm.QuickPlot(
                sim,
                labels=["Default initial conditions", "Fully charged"],
                time_unit="seconds",
            )
            plot.plot(time)
            plot.fig.savefig("foo.png", dpi=300)
            print(sol_US06_1)
            solved = True

        except:
            pass
            # print("Exception")
    return time, cycle
Beispiel #27
0
    geometry = model.default_geometry
    param.process_geometry(geometry)
    mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts)
    disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
    disc.process_model(model)

# solve model
solutions = [None] * len(models)
t_eval = np.linspace(0, 3600 * 2, 1000)
for i, model in enumerate(models):
    solution = model.default_solver.solve(model, t_eval)
    solutions[i] = solution

# plot
output_variables = [
    "Interfacial current density [A.m-2]",
    "Electrolyte concentration [mol.m-3]",
    "Current [A]",
    "Porosity",
    "Electrolyte potential [V]",
    "Terminal voltage [V]",
    "Negative electrode reaction overpotential",
    "Positive electrode reaction overpotential",
    "Sum of interfacial current densities",
    "Sum of electrolyte reaction source terms",
]
plot = pybamm.QuickPlot(solutions,
                        output_variables,
                        linestyles=[":", "--", "-"])
plot.dynamic_plot()
# load model
pybamm.set_logging_level("INFO")
model = pybamm.lithium_ion.SPMe()

# create geometry
geometry = model.default_geometry

# load parameter values and process model and geometry
param = model.default_parameter_values
param["Current function"] = pybamm.GetUserCurrent(car_current)
param.process_model(model)
param.process_geometry(geometry)

# set mesh
mesh = pybamm.Mesh(geometry, model.default_submesh_types,
                   model.default_var_pts)

# discretise model
disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
disc.process_model(model)

# simulate car current for 30 minutes
tau = param.process_symbol(
    pybamm.standard_parameters_lithium_ion.tau_discharge).evaluate(0)
t_eval = np.linspace(0, 1800 / tau, 600)
solution = model.default_solver.solve(model, t_eval)

# plot
plot = pybamm.QuickPlot(model, mesh, solution)
plot.dynamic_plot()
Beispiel #29
0
# build model
model.build_model()

# create geometry
geometry = pybamm.Geometry("1D macro", "1D micro")

# process model and geometry
param = model.default_parameter_values
param.process_model(model)
param.process_geometry(geometry)

# set mesh
# Note: li-ion base model has defaults for mesh and var_pts
mesh = pybamm.Mesh(geometry, model.default_submesh_types,
                   model.default_var_pts)

# discretise model
# Note: li-ion base model has default spatial methods
disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
disc.process_model(model)

# solve model
t_eval = np.linspace(0, 3600, 100)
solver = pybamm.ScipySolver()
solution = solver.solve(model, t_eval)

# plot
plot = pybamm.QuickPlot(solution)
plot.dynamic_plot()
Beispiel #30
0
var_pts = model.default_var_pts
mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts)

# discretise model
disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
disc.process_model(model)

# solve model
t_eval = np.linspace(0, 7200, 1000)
solver = pybamm.CasadiSolver(mode="safe", atol=1e-6, rtol=1e-3)
solution = solver.solve(model, t_eval)

# plot
plot = pybamm.QuickPlot(
    solution,
    [
        "Working particle concentration [mol.m-3]",
        "Electrolyte concentration [mol.m-3]",
        "Current [A]",
        "Working electrode potential [V]",
        "Electrolyte potential [V]",
        "Total electrolyte concentration",
        "Total lithium in working electrode [mol]",
        "Working electrode open circuit potential [V]",
        ["Terminal voltage [V]", "Voltage drop in the cell [V]"],
    ],
    time_unit="seconds",
    spatial_unit="um",
)
plot.dynamic_plot()