Ejemplo n.º 1
0
    def test_termination(self):
        experiment = pybamm.Experiment(["Discharge at 1 C for 20 seconds"])
        self.assertEqual(experiment.termination, {})

        experiment = pybamm.Experiment(["Discharge at 1 C for 20 seconds"],
                                       termination="80.7% capacity")
        self.assertEqual(experiment.termination, {"capacity": (80.7, "%")})
        experiment = pybamm.Experiment(["Discharge at 1 C for 20 seconds"],
                                       termination="80.7 % capacity")
        self.assertEqual(experiment.termination, {"capacity": (80.7, "%")})

        experiment = pybamm.Experiment(["Discharge at 1 C for 20 seconds"],
                                       termination="4.1Ah capacity")
        self.assertEqual(experiment.termination, {"capacity": (4.1, "Ah")})
        experiment = pybamm.Experiment(["Discharge at 1 C for 20 seconds"],
                                       termination="4.1 A.h capacity")
        self.assertEqual(experiment.termination, {"capacity": (4.1, "Ah")})

        with self.assertRaisesRegex(ValueError, "Only capacity"):
            experiment = pybamm.Experiment(["Discharge at 1 C for 20 seconds"],
                                           termination="bla bla capacity bla")
        with self.assertRaisesRegex(ValueError, "Only capacity"):
            experiment = pybamm.Experiment(["Discharge at 1 C for 20 seconds"],
                                           termination="4 A.h something else")
        with self.assertRaisesRegex(ValueError, "Capacity termination"):
            experiment = pybamm.Experiment(["Discharge at 1 C for 20 seconds"],
                                           termination="1 capacity")
 def __init__(
     self,
     models_for_comp,
     chemistry,
     is_experiment,
     params,
     cycle=None,
     number=None,
     param_to_vary_info=None,
     varied_values_override=None,
 ):
     self.models_for_comp = models_for_comp
     self.chemistry = chemistry
     self.is_experiment = is_experiment
     self.cycle = cycle
     self.number = number
     self.param_to_vary = (list(param_to_vary_info.keys())[0]
                           if param_to_vary_info is not None else None)
     self.bounds = (list(param_to_vary_info.values())[0]["bounds"]
                    if param_to_vary_info is not None else None)
     self.print_name = (list(param_to_vary_info.values())[0]["print_name"]
                        if param_to_vary_info is not None else None)
     self.parameter_values = pybamm.ParameterValues(self.chemistry)
     self.experiment = (dict(
         list(enumerate([pybamm.Experiment(self.cycle * self.number)])))
                        if self.cycle is not None else None)
     self.comparison_dict = {}
     self.params = params
     self.varied_values_override = varied_values_override
Ejemplo n.º 3
0
    def test_save_at_cycles(self):
        experiment = pybamm.Experiment([
            (
                "Discharge at 1C until 3.3V",
                "Charge at 1C until 4.1 V",
                "Hold at 4.1V until C/10",
            ),
        ] * 10, )
        model = pybamm.lithium_ion.SPM()
        sim = pybamm.Simulation(model, experiment=experiment)
        sol = sim.solve(solver=pybamm.CasadiSolver("fast with events"),
                        save_at_cycles=2)
        # Solution saves "None" for the cycles that are not saved
        for cycle_num in [2, 4, 6, 8]:
            self.assertIsNone(sol.cycles[cycle_num])
        for cycle_num in [0, 1, 3, 5, 7, 9]:
            self.assertIsNotNone(sol.cycles[cycle_num])
        # Summary variables are not None
        self.assertIsNotNone(sol.summary_variables["Capacity [A.h]"])

        sol = sim.solve(solver=pybamm.CasadiSolver("fast with events"),
                        save_at_cycles=[3, 4, 5, 9])
        # Note offset by 1 (0th cycle is cycle 1)
        for cycle_num in [1, 5, 6, 7, 9]:
            self.assertIsNone(sol.cycles[cycle_num])
        for cycle_num in [0, 2, 3, 4, 8]:
            self.assertIsNotNone(sol.cycles[cycle_num])
        # Summary variables are not None
        self.assertIsNotNone(sol.summary_variables["Capacity [A.h]"])
Ejemplo n.º 4
0
def compare_data(models, param, Crates, temperature, cells_ignore=None, filename=None):
    fig, axes = plt.subplots(3, 2, figsize=(5.7, 5.5))

    for k, Crate in enumerate(Crates):
        param = set_experiment_parameters(param, Crate, temperature)
        param = set_ambient_temperature(param, Crate, temperature)

        experiment = pybamm.Experiment(
            [
                "Discharge at {}C until 2.5 V (5 seconds period)".format(Crate),
                "Rest for 2 hours",
            ],
            period="30 seconds",
        )

        solutions = []

        axes[k, :], _ = plot_experimental_data(
            axes[k, :], Crate, temperature, cells_ignore
        )

        for model in models:
            simulation = pybamm.Simulation(
                model,
                parameter_values=param,
                experiment=experiment,
            )
            simulation.solve()
            solution = simulation.solution
            solutions.append(solution)

            axes[k, :] = plot_model_solutions(axes[k, :], solution, Crate, temperature)

    fig.suptitle("Ambient temperature: {} °C".format(temperature))

    fig.tight_layout()
    fig.subplots_adjust(left=0.15, top=0.92)

    return fig


# Define models
    pybamm.lithium_ion.SPMe(
        options={
            "thermal": "lumped",
            "dimensionality": 0,
            "cell geometry": "arbitrary",
            "electrolyte conductivity": "integrated",
        },
        name="TSPMe",
    ),
    pybamm.lithium_ion.DFN(
        options={
            "thermal": "lumped",
            "dimensionality": 0,
            "cell geometry": "arbitrary",
        },
        name="TDFN",
    ),
Ejemplo n.º 5
0
    def test_run_experiment_termination(self):
        # with percent
        experiment = pybamm.Experiment(
            [
                (
                    "Discharge at 1C until 3V",
                    "Charge at 1C until 4.2 V",
                    "Hold at 4.2V until C/10",
                ),
            ] * 10,
            termination="99% capacity",
        )
        model = pybamm.lithium_ion.SPM({"SEI": "ec reaction limited"})
        param = pybamm.ParameterValues(
            chemistry=pybamm.parameter_sets.Chen2020)
        param["SEI kinetic rate constant [m.s-1]"] = 1e-14
        sim = pybamm.Simulation(model,
                                experiment=experiment,
                                parameter_values=param)
        sol = sim.solve(solver=pybamm.CasadiSolver())
        C = sol.summary_variables["Capacity [A.h]"]
        np.testing.assert_array_less(np.diff(C), 0)
        # all but the last value should be above the termination condition
        np.testing.assert_array_less(0.99 * C[0], C[:-1])

        # with Ah value
        experiment = pybamm.Experiment(
            [
                (
                    "Discharge at 1C until 3V",
                    "Charge at 1C until 4.2 V",
                    "Hold at 4.2V until C/10",
                ),
            ] * 10,
            termination="5.04Ah capacity",
        )
        model = pybamm.lithium_ion.SPM({"SEI": "ec reaction limited"})
        param = pybamm.ParameterValues(
            chemistry=pybamm.parameter_sets.Chen2020)
        param["SEI kinetic rate constant [m.s-1]"] = 1e-14
        sim = pybamm.Simulation(model,
                                experiment=experiment,
                                parameter_values=param)
        sol = sim.solve(solver=pybamm.CasadiSolver())
        # all but the last value should be above the termination condition
        np.testing.assert_array_less(5.04, C[:-1])
Ejemplo n.º 6
0
 def test_read_strings(self):
     experiment = pybamm.Experiment(
         [
             "Discharge at 1C for 0.5 hours",
             "Discharge at C/20 for 0.5 hours",
             "Charge at 0.5 C for 45 minutes",
             "Discharge at 1 A for 0.5 hours",
             "Charge at 200 mA for 45 minutes (1 minute period)",
             "Discharge at 1W for 0.5 hours",
             "Charge at 200 mW for 45 minutes",
             "Rest for 10 minutes (5 minute period)",
             "Hold at 1V for 20 seconds",
             "Charge at 1 C until 4.1V",
             "Hold at 4.1 V until 50mA",
             "Hold at 3V until C/50",
             "Discharge at C/3 for 2 hours or until 2.5 V",
         ],
         {"test": "test"},
         period="20 seconds",
     )
     self.assertEqual(
         experiment.operating_conditions,
         [
             (1, "C", 1800.0, 20.0),
             (0.05, "C", 1800.0, 20.0),
             (-0.5, "C", 2700.0, 20.0),
             (1, "A", 1800.0, 20.0),
             (-0.2, "A", 2700.0, 60.0),
             (1, "W", 1800.0, 20.0),
             (-0.2, "W", 2700.0, 20.0),
             (0, "A", 600.0, 300.0),
             (1, "V", 20.0, 20.0),
             (-1, "C", None, 20.0),
             (4.1, "V", None, 20.0),
             (3, "V", None, 20.0),
             (1 / 3, "C", 7200.0, 20.0),
         ],
     )
     self.assertEqual(
         experiment.events,
         [
             None,
             None,
             None,
             None,
             None,
             None,
             None,
             None,
             None,
             (4.1, "V"),
             (0.05, "A"),
             (0.02, "C"),
             (2.5, "V"),
         ],
     )
     self.assertEqual(experiment.parameters, {"test": "test"})
     self.assertEqual(experiment.period, 20)
    def test_experiment_generator_with_rest(self):
        cycle = experiment_generator({"rest1": True, "rest2": True})
        self.assertEqual(len(cycle[0]), 5)
        self.assertEqual(cycle[0][0][:9], "Discharge")
        self.assertEqual(cycle[0][1][:4], "Rest")
        self.assertEqual(cycle[0][2][:6], "Charge")
        self.assertEqual(cycle[0][3][:4], "Hold")
        self.assertEqual(cycle[0][4][:4], "Rest")

        pybamm.Experiment(cycle)
Ejemplo n.º 8
0
 def test_run_experiment_breaks_early(self):
     experiment = pybamm.Experiment(["Discharge at 2 C for 1 hour"])
     model = pybamm.lithium_ion.SPM()
     sim = pybamm.Simulation(model, experiment=experiment)
     pybamm.set_logging_level("ERROR")
     # giving the time, should get ignored
     t_eval = [0, 1]
     sim.solve(t_eval, solver=pybamm.CasadiSolver())
     pybamm.set_logging_level("WARNING")
     self.assertEqual(sim._solution, None)
Ejemplo n.º 9
0
 def test_run_experiment(self):
     experiment = pybamm.Experiment([
         "Discharge at C/20 for 1 hour",
         "Charge at 1 A until 4.1 V",
         "Hold at 4.1 V until C/2",
         "Discharge at 2 W for 1 hour",
     ])
     model = pybamm.lithium_ion.SPM()
     sim = pybamm.Simulation(model, experiment=experiment)
     sim.solve(solver=pybamm.CasadiSolver())
     self.assertEqual(sim._solution.termination, "final time")
Ejemplo n.º 10
0
 def test_dfn_half_cell_simulation_with_experiment_error(self):
     options = {"working electrode": "negative"}
     model = pybamm.lithium_ion.BasicDFNHalfCell(options=options)
     experiment = pybamm.Experiment([
         ("Discharge at C/10 for 10 hours or until 3.5 V")
     ])
     with self.assertRaisesRegex(
             NotImplementedError,
             "BasicDFNHalfCell is not compatible with experiment simulations yet."
     ):
         pybamm.Simulation(model, experiment=experiment)
Ejemplo n.º 11
0
 def test_str_repr(self):
     conds = [
         "Discharge at 1 C for 20 seconds", "Charge at 0.5 W for 10 minutes"
     ]
     experiment = pybamm.Experiment(conds)
     self.assertEqual(str(experiment), str(conds))
     self.assertEqual(
         repr(experiment),
         "pybamm.Experiment(['Discharge at 1 C for 20 seconds'" +
         ", 'Charge at 0.5 W for 10 minutes'])",
     )
Ejemplo n.º 12
0
 def test_infeasible(self):
     experiment = pybamm.Experiment([
         ("Discharge at 1C for 0.5 hours", ),
     ] * 4)
     model = pybamm.lithium_ion.SPM()
     sim = pybamm.Simulation(model,
                             experiment=experiment,
                             solver=pybamm.CasadiSolver())
     sol = sim.solve()
     # this experiment fails during the third cycle (i.e. is infeasible)
     # so we should just return the successful cycles (2 in this case)
     self.assertEqual(len(sol.cycles), 2)
Ejemplo n.º 13
0
 def time_setup_SPMe_simulation(self, with_experiment):
     self.model = pybamm.lithium_ion.SPMe()
     if with_experiment:
         exp = pybamm.Experiment([
             "Discharge at 0.1C until 3.105 V",
         ])
         pybamm.Simulation(self.model,
                           parameter_values=self.param,
                           experiment=exp)
     else:
         pybamm.Simulation(self.model,
                           parameter_values=self.param,
                           C_rate=1)
def compare_data(models,
                 param,
                 Crates,
                 temperature,
                 cells_ignore=None,
                 filename=None):
    fig, axes = plt.subplots(3, 2, figsize=(5.7, 5.5))

    for k, Crate in enumerate(Crates):
        param = set_experiment_parameters(param, Crate, temperature)
        param = set_ambient_temperature(param, Crate, temperature)

        experiment = pybamm.Experiment(
            [
                "Discharge at {}C until 2.5 V (5 seconds period)".format(
                    Crate),
                "Rest for 2 hours",
            ],
            period="30 seconds",
        )

        solutions = []

        axes[k, :], data_conc = plot_experimental_data(axes[k, :], Crate,
                                                       temperature,
                                                       cells_ignore)

        for model in models:
            simulation = pybamm.Simulation(
                model,
                parameter_values=param,
                experiment=experiment,
            )
            simulation.solve()
            solution = simulation.solution
            solutions.append(solution)

            axes[k, :] = plot_model_solutions(axes[k, :], solution, Crate,
                                              temperature)
            error = compute_error(solution, data_conc)
            idx = filename.index(".")
            new_filename = filename[:idx] + "_" + model.name + filename[idx:]
            print_error(error, Crate, temperature, filename=new_filename)

    fig.suptitle("Ambient temperature: {} °C".format(temperature))

    fig.tight_layout()
    fig.subplots_adjust(left=0.15, top=0.92)

    return fig
Ejemplo n.º 15
0
 def test_read_strings_repeat(self):
     experiment = pybamm.Experiment(
         ["Discharge at 10 mA for 0.5 hours"] +
         ["Charge at 0.5 C for 45 minutes", "Hold at 1 V for 20 seconds"] *
         2)
     self.assertEqual(
         experiment.operating_conditions,
         [
             (0.01, "A", 1800.0, 60),
             (-0.5, "C", 2700.0, 60),
             (1, "V", 20.0, 60),
             (-0.5, "C", 2700.0, 60),
             (1, "V", 20.0, 60),
         ],
     )
     self.assertEqual(experiment.period, 60)
Ejemplo n.º 16
0
 def test_gitt(self):
     experiment = pybamm.Experiment(
         ["Discharge at C/20 for 1 hour", "Rest for 1 hour"] * 10,
         period="6 minutes")
     model = pybamm.lithium_ion.SPM()
     sim = pybamm.Simulation(model,
                             experiment=experiment,
                             solver=pybamm.CasadiSolver())
     sim.solve()
     np.testing.assert_array_almost_equal(sim._solution["Time [h]"].entries,
                                          np.arange(0, 20.01, 0.1))
     cap = model.default_parameter_values["Cell capacity [A.h]"]
     np.testing.assert_array_almost_equal(
         sim._solution["Current [A]"].entries,
         [cap / 20] * 11 + [0] * 10 + ([cap / 20] * 10 + [0] * 10) * 9,
     )
Ejemplo n.º 17
0
 def test_run_experiment_old_setup_type(self):
     experiment = pybamm.Experiment(
         [
             (
                 "Discharge at C/20 for 1 hour",
                 "Charge at 1 A until 4.1 V",
                 "Hold at 4.1 V until C/2",
                 "Discharge at 2 W for 1 hour",
             ),
         ],
         use_simulation_setup_type="old",
     )
     model = pybamm.lithium_ion.SPM()
     sim = pybamm.Simulation(model, experiment=experiment)
     solution1 = sim.solve(solver=pybamm.CasadiSolver())
     self.assertEqual(solution1.termination, "final time")
Ejemplo n.º 18
0
 def test_cycle_unpacking(self):
     experiment = pybamm.Experiment([
         ("Discharge at C/20 for 0.5 hours",
          "Charge at C/5 for 45 minutes"),
         ("Discharge at C/20 for 0.5 hours"),
         "Charge at C/5 for 45 minutes",
     ])
     self.assertEqual(
         experiment.operating_conditions,
         [
             (0.05, "C", 1800.0, 60.0),
             (-0.2, "C", 2700.0, 60.0),
             (0.05, "C", 1800.0, 60.0),
             (-0.2, "C", 2700.0, 60.0),
         ],
     )
     self.assertEqual(experiment.cycle_lengths, [2, 1, 1])
    def test_inputs(self):
        experiment = pybamm.Experiment(
            ["Discharge at C/2 for 1 hour", "Rest for 1 hour"]
        )
        model = pybamm.lithium_ion.SPM()

        # Change a parameter to an input
        param = pybamm.ParameterValues(chemistry=pybamm.parameter_sets.Marquis2019)
        param["Negative electrode diffusivity [m2.s-1]"] = (
            pybamm.InputParameter("Dsn") * 3.9e-14
        )

        # Solve a first time
        sim = pybamm.Simulation(model, experiment=experiment, parameter_values=param)
        sim.solve(inputs={"Dsn": 1})
        np.testing.assert_array_equal(sim.solution.inputs["Dsn"], 1)

        # Solve again, input should change
        sim.solve(inputs={"Dsn": 2})
        np.testing.assert_array_equal(sim.solution.inputs["Dsn"], 2)
Ejemplo n.º 20
0
 def test_rest_discharge_rest(self):
     # An experiment which requires recomputing consistent states
     experiment = pybamm.Experiment(
         [
             "Rest for 5 minutes", "Discharge at 0.1C until 3V",
             "Rest for 30 minutes"
         ],
         period="1 minute",
     )
     parameter_values = pybamm.ParameterValues(
         chemistry=pybamm.parameter_sets.Chen2020)
     model = pybamm.lithium_ion.DFN()
     sim = pybamm.Simulation(
         model,
         parameter_values=parameter_values,
         experiment=experiment,
         solver=pybamm.CasadiSolver(),
     )
     sol = sim.solve()
     np.testing.assert_array_almost_equal(sol["Current [A]"].data[:5], 0)
     np.testing.assert_array_almost_equal(sol["Current [A]"].data[-29:], 0)
Ejemplo n.º 21
0
 def test_discharge_rest_charge(self):
     experiment = pybamm.Experiment(
         [
             "Discharge at C/2 for 1 hour",
             "Rest for 1 hour",
             "Charge at C/2 for 1 hour",
         ],
         period="0.25 hours",
     )
     model = pybamm.lithium_ion.SPM()
     sim = pybamm.Simulation(model,
                             experiment=experiment,
                             solver=pybamm.CasadiSolver())
     sim.solve()
     np.testing.assert_array_almost_equal(sim._solution["Time [h]"].entries,
                                          np.linspace(0, 3, 13))
     cap = model.default_parameter_values["Cell capacity [A.h]"]
     np.testing.assert_array_almost_equal(
         sim._solution["Current [A]"].entries,
         [cap / 2] * 5 + [0] * 4 + [-cap / 2] * 4,
     )
Ejemplo n.º 22
0
 def test_bad_strings(self):
     with self.assertRaisesRegex(TypeError,
                                 "Operating conditions should be strings"):
         pybamm.Experiment([1, 2, 3])
     with self.assertRaisesRegex(ValueError,
                                 "Operating conditions must contain"):
         pybamm.Experiment(["Discharge at 1 A at 2 hours"])
     with self.assertRaisesRegex(ValueError, "instruction must be"):
         pybamm.Experiment(["Run at 1 A for 2 hours"])
     with self.assertRaisesRegex(
             ValueError, "Instruction 'Run at at 1 A' not recognized"):
         pybamm.Experiment(["Run at at 1 A for 2 hours"])
     with self.assertRaisesRegex(ValueError, "units must be"):
         pybamm.Experiment(["Discharge at 1 B for 2 hours"])
     with self.assertRaisesRegex(ValueError, "time units must be"):
         pybamm.Experiment(["Discharge at 1 A for 2 years"])
     with self.assertRaisesRegex(
             TypeError, "experimental parameters should be a dictionary"):
         pybamm.Experiment([], "not a dictionary")
Ejemplo n.º 23
0
    def test_cycles(self):
        model = pybamm.lithium_ion.SPM()
        experiment = pybamm.Experiment([
            ("Discharge at C/20 for 0.5 hours",
             "Charge at C/20 for 15 minutes"),
            ("Discharge at C/20 for 0.5 hours",
             "Charge at C/20 for 15 minutes"),
        ])
        sim = pybamm.Simulation(model, experiment=experiment)
        sol = sim.solve()
        self.assertEqual(len(sol.cycles), 2)
        len_cycle_1 = len(sol.cycles[0].t)

        self.assertIsInstance(sol.cycles[0], pybamm.Solution)
        np.testing.assert_array_equal(sol.cycles[0].t, sol.t[:len_cycle_1])
        np.testing.assert_array_equal(sol.cycles[0].y, sol.y[:, :len_cycle_1])

        self.assertIsInstance(sol.cycles[1], pybamm.Solution)
        np.testing.assert_array_equal(sol.cycles[1].t, sol.t[len_cycle_1 - 1:])
        np.testing.assert_array_equal(sol.cycles[1].y, sol.y[:,
                                                             len_cycle_1 - 1:])
 def setUp(self):
     self.model = pybamm.lithium_ion.SPM(
         options={"SEI": "electron-migration limited"})
     self.cycle = [(
         "Discharge at 2 C until 3.6 V",
         "Charge at 3 C until 3.8 V",
         "Hold at 3.8 V until 98 mA",
         "Rest for 4 minutes",
     )]
     self.number = 2
     self.experiment = pybamm.Experiment(self.cycle * self.number)
     self.is_experiment = False
     self.degradation_parameter = "Inner SEI open-circuit potential [V]"
     self.varied_values = [0.09, 0.05]
     self.param_values_mohtat = []
     for i in range(2):
         self.param_values_mohtat.append(
             pybamm.ParameterValues(pybamm.parameter_sets.Mohtat2020))
         self.param_values_mohtat[i][
             "Inner SEI open-circuit potential [V]"] = self.varied_values[i]
     self.chemistry = pybamm.parameter_sets.Mohtat2020
     self.parameter_values = pybamm.ParameterValues(self.chemistry)
    def test_experiment_generator_with_random_experiment(self):
        cycle = experiment_generator()
        self.assertTrue(
            len(cycle[0]) == 5 or len(cycle[0]) == 3 or len(cycle[0]) == 4)
        self.assertEqual(cycle[0][0][:9], "Discharge")

        if len(cycle[0]) == 3:
            self.assertEqual(cycle[0][1][:6], "Charge")
            self.assertEqual(cycle[0][2][:4], "Hold")
        elif len(cycle[0]) == 4:
            if cycle[0][1][:4] == "Rest":
                self.assertEqual(cycle[0][2][:6], "Charge")
                self.assertEqual(cycle[0][3][:4], "Hold")
            elif cycle[0][3][:4] == "Rest":
                self.assertEqual(cycle[0][1][:6], "Charge")
                self.assertEqual(cycle[0][2][:4], "Hold")
        elif len(cycle[0]) == 5:
            self.assertEqual(cycle[0][1][:4], "Rest")
            self.assertEqual(cycle[0][2][:6], "Charge")
            self.assertEqual(cycle[0][3][:4], "Hold")
            self.assertEqual(cycle[0][4][:4], "Rest")

        pybamm.Experiment(cycle)
Ejemplo n.º 26
0
    def test_interpolant_extrapolate(self):
        model = pybamm.lithium_ion.DFN()
        param = pybamm.ParameterValues(
            chemistry=pybamm.parameter_sets.NCA_Kim2011)
        experiment = pybamm.Experiment(["Charge at 1C until 4.6 V"],
                                       period="10 seconds")

        param["Upper voltage cut-off [V]"] = 4.8

        sim = pybamm.Simulation(
            model,
            parameter_values=param,
            experiment=experiment,
            solver=pybamm.CasadiSolver(
                mode="safe",
                dt_max=0.001,
                extrap_tol=1e-3,
                extra_options_setup={"max_num_steps": 500},
            ),
        )
        with self.assertRaisesRegex(pybamm.SolverError,
                                    "interpolation bounds"):
            sim.solve()

        ci = param["Initial concentration in positive electrode [mol.m-3]"]
        param[
            "Initial concentration in positive electrode [mol.m-3]"] = 0.8 * ci

        sim = pybamm.Simulation(
            model,
            parameter_values=param,
            experiment=experiment,
            solver=pybamm.CasadiSolver(mode="safe", dt_max=0.05),
        )
        with self.assertRaisesRegex(pybamm.SolverError,
                                    "interpolation bounds"):
            sim.solve()
Ejemplo n.º 27
0
    def test_run_experiment(self):
        experiment = pybamm.Experiment([(
            "Discharge at C/20 for 1 hour",
            "Charge at 1 A until 4.1 V",
            "Hold at 4.1 V until C/2",
            "Discharge at 2 W for 1 hour",
        )])
        model = pybamm.lithium_ion.DFN()
        sim = pybamm.Simulation(model, experiment=experiment)
        sol = sim.solve()
        self.assertEqual(sol.termination, "final time")
        self.assertEqual(len(sol.cycles), 1)

        for i, step in enumerate(sol.cycles[0].steps[:-1]):
            len_rhs = sol.all_models[0].concatenated_rhs.size
            y_left = step.all_ys[-1][:len_rhs, -1]
            if isinstance(y_left, casadi.DM):
                y_left = y_left.full()
            y_right = sol.cycles[0].steps[i + 1].all_ys[0][:len_rhs, 0]
            if isinstance(y_right, casadi.DM):
                y_right = y_right.full()
            np.testing.assert_array_equal(y_left.flatten(), y_right.flatten())

        # Solve again starting from solution
        sol2 = sim.solve(starting_solution=sol)
        self.assertEqual(sol2.termination, "final time")
        self.assertGreater(sol2.t[-1], sol.t[-1])
        self.assertEqual(sol2.cycles[0], sol.cycles[0])
        self.assertEqual(len(sol2.cycles), 2)
        # Check starting solution is unchanged
        self.assertEqual(len(sol.cycles), 1)

        # save
        sol2.save("test_experiment.sav")
        sol3 = pybamm.load("test_experiment.sav")
        self.assertEqual(len(sol3.cycles), 2)
        os.remove("test_experiment.sav")
Ejemplo n.º 28
0
#
# Constant-current constant-voltage charge
#
import pybamm
import matplotlib.pyplot as plt

pybamm.set_logging_level("INFO")
experiment = pybamm.Experiment(
    [
        "Discharge at C/10 for 13 hours or until 3.3 V",
        "Rest for 1 hour",
        "Charge at 1 A until 4.1 V",
        "Hold at 4.1 V until 50 mA",
        "Rest for 1 hour",
    ] * 3,
    period="2 minutes",
)
model = pybamm.lithium_ion.DFN(
)  # use {"thermal": "x-lumped"} for thermal effects
sim = pybamm.Simulation(model,
                        experiment=experiment,
                        solver=pybamm.CasadiSolver())
sim.solve()

# Plot voltages from the discharge segments only
fig, ax = plt.subplots()
for i in range(3):
    # Extract sub solutions
    sol = sim.solution.sub_solutions[i * 5]
    # Extract variables
    t = sol["Time [h]"].entries
Ejemplo n.º 29
0
experiment = pb.Experiment([(
    "Charge at 1 C until 4.2 V",
    "Hold at 4.2 V until C/10",
    "Rest for 5 minutes",
    "Discharge at 1 C until 2.8 V",
    "Rest for 5 minutes",
)] * 2 + [
    (
        "Charge at 1 C until 4.2 V",
        "Hold at 4.2 V until C/20",
        "Rest for 30 minutes",
        "Discharge at C/3 until 2.8 V",
    ),
    (
        "Charge at 1 C until 4.2 V",
        "Hold at 4.2 V until C/20",
        "Rest for 30 minutes",
        "Discharge at 1 C until 2.8 V",
    ),
    # (
    #     "Charge at 1 C until 4.2 V",
    #     "Hold at 4.2 V until C/20",
    #     "Rest for 30 minutes",
    #     "Discharge at 2 C until 2.8 V",
    # ),
    # (
    #     "Charge at 1 C until 4.2 V",
    #     "Hold at 4.2 V until C/20",
    #     "Rest for 30 minutes",
    #     "Discharge at 3 C until 2.8 V",
    # ),
])
Ejemplo n.º 30
0
    def test_set_up(self):
        experiment = pybamm.Experiment([
            "Discharge at C/20 for 1 hour",
            "Charge at 1 A until 4.1 V",
            "Hold at 4.1 V until 50 mA",
            "Discharge at 2 W for 1 hour",
        ])
        model = pybamm.lithium_ion.DFN()
        sim = pybamm.Simulation(model, experiment=experiment)

        self.assertEqual(sim.experiment, experiment)
        self.assertEqual(
            sim._experiment_inputs[0]["Current input [A]"],
            1 / 20 *
            model.default_parameter_values["Nominal cell capacity [A.h]"],
        )
        self.assertEqual(sim._experiment_inputs[0]["Current switch"], 1)
        self.assertEqual(sim._experiment_inputs[0]["Voltage switch"], 0)
        self.assertEqual(sim._experiment_inputs[0]["Power switch"], 0)
        self.assertEqual(sim._experiment_inputs[0]["Current cut-off [A]"],
                         -1e10)
        self.assertEqual(sim._experiment_inputs[0]["Voltage cut-off [V]"],
                         -1e10)
        self.assertEqual(sim._experiment_inputs[1]["Current input [A]"], -1)
        self.assertEqual(sim._experiment_inputs[1]["Current switch"], 1)
        self.assertEqual(sim._experiment_inputs[1]["Voltage switch"], 0)
        self.assertEqual(sim._experiment_inputs[1]["Power switch"], 0)
        self.assertEqual(sim._experiment_inputs[1]["Current cut-off [A]"],
                         -1e10)
        self.assertEqual(sim._experiment_inputs[1]["Voltage cut-off [V]"], 4.1)
        self.assertEqual(sim._experiment_inputs[2]["Current switch"], 0)
        self.assertEqual(sim._experiment_inputs[2]["Voltage switch"], 1)
        self.assertEqual(sim._experiment_inputs[2]["Power switch"], 0)
        self.assertEqual(sim._experiment_inputs[2]["Voltage input [V]"], 4.1)
        self.assertEqual(sim._experiment_inputs[2]["Current cut-off [A]"],
                         0.05)
        self.assertEqual(sim._experiment_inputs[2]["Voltage cut-off [V]"],
                         -1e10)
        self.assertEqual(sim._experiment_inputs[3]["Current switch"], 0)
        self.assertEqual(sim._experiment_inputs[3]["Voltage switch"], 0)
        self.assertEqual(sim._experiment_inputs[3]["Power switch"], 1)
        self.assertEqual(sim._experiment_inputs[3]["Power input [W]"], 2)
        self.assertEqual(sim._experiment_inputs[3]["Current cut-off [A]"],
                         -1e10)
        self.assertEqual(sim._experiment_inputs[3]["Voltage cut-off [V]"],
                         -1e10)

        Crate = 1 / model.default_parameter_values[
            "Nominal cell capacity [A.h]"]
        self.assertEqual(sim._experiment_times,
                         [3600, 3 / Crate * 3600, 24 * 3600, 3600])

        model_I = sim.op_conds_to_model_and_param[(-1.0, "A")][0]
        model_V = sim.op_conds_to_model_and_param[(4.1, "V")][0]
        self.assertIn(
            "Current cut-off (positive) [A] [experiment]",
            [event.name for event in model_V.events],
        )
        self.assertIn(
            "Current cut-off (negative) [A] [experiment]",
            [event.name for event in model_V.events],
        )
        self.assertIn(
            "Voltage cut-off [V] [experiment]",
            [event.name for event in model_I.events],
        )

        # fails if trying to set up with something that isn't an experiment
        with self.assertRaisesRegex(TypeError, "experiment must be"):
            pybamm.Simulation(model, experiment=0)