Skip to content

Example of jelly roll

This example demonstrates how to set up, run and visualize a 3D cylindrical battery model

Load the packages

julia
using BattMo, GLMakie, Jutul

Load the cell parameters

julia
cell_parameters     = load_cell_parameters(; from_default_set = "Chen2020")
cycling_protocol    = load_cycling_protocol(; from_default_set = "CCDischarge")
model_settings      = load_model_settings(; from_default_set = "P4D_cylindrical")
simulation_settings = load_simulation_settings(; from_default_set = "P4D_cylindrical")

Set up the model

julia
model_setup = LithiumIonBattery(; model_settings)
✔️ Validation of ModelSettings passed: No issues found.
──────────────────────────────────────────────────

Review and modify the cell parameters

We go through some of the geometrical and discretization parameters. We modify some of them to obtain a cell where the different components are easier to visualize

The cell geometry is determined by the inner and outer radius and the height. We reduce the outer radius

julia
cell_parameters["Cell"]["OuterRadius"] = 0.010

We modify the current collector thicknesses, for visualization purpose

julia
cell_parameters["NegativeElectrode"]["CurrentCollector"]["Thickness"]    = 50e-6
cell_parameters["PositiveElectrode"]["CurrentCollector"]["Thickness"]    = 50e-6

The tabs are part of the current collectors that connect the electrodes to the external circuit. The location of the tabs is given as a fraction length, where the length is measured along the current collector in the horizontal direction, meaning that we follow the rolling spiral. Indeed, this is the relevant length to use if we want to dispatch the current collector in a equilibrated way, where each of them will a priori collect the same amount of current. In the following, we include three tabs with one in the middle and the other at a distance such that each tab will collect one third of the current

julia
cell_parameters["NegativeElectrode"]["CurrentCollector"]["TabFractions"] = [0.5/3, 0.5, 0.5 + 0.5/3]
cell_parameters["PositiveElectrode"]["CurrentCollector"]["TabFractions"] = [0.5/3, 0.5, 0.5 + 0.5/3]

We set the tab width to 2 mm

julia
cell_parameters["NegativeElectrode"]["CurrentCollector"]["TabWidth"] = 0.002
cell_parameters["PositiveElectrode"]["CurrentCollector"]["TabWidth"] = 0.002

The angular discretization of the cell is determined by the number of angular grid points.

julia
simulation_settings["GridResolution"]["Angular"] = 30

Create the simulation object

julia
sim = Simulation(model_setup, cell_parameters, cycling_protocol; simulation_settings);
✔️ Validation of CellParameters passed: No issues found.
──────────────────────────────────────────────────
✔️ Validation of CyclingProtocol passed: No issues found.
──────────────────────────────────────────────────
✔️ Validation of SimulationSettings passed: No issues found.
──────────────────────────────────────────────────

We preprocess the simulation object to retrieve the grids and coupling structure, which we want to visualize prior running the simulation

julia
output = get_simulation_input(sim)
grids     = output[:grids]
couplings = output[:couplings]

Visualize the grids and couplings

Define a list of the component to iterate over in the ploting routin below

julia
components = ["NegativeElectrode", "PositiveElectrode", "NegativeCurrentCollector", "PositiveCurrentCollector" ]
colors = [:gray, :green, :blue, :black]

We plot the components

julia
for (i, component) in enumerate(components)
    if i == 1
        global fig, ax = plot_mesh(grids[component],
                            color = colors[i])
    else
        plot_mesh!(ax,
                   grids[component],
                   color = colors[i])
    end
end

Plot the current collectors tabs

We plot the tabs, which couple the current collectors with the external circuits. The tabs will typically protude from the cell in the vertical directions but we can neglect this 3d feature in the simulation model. The tabs are then represented by horizontal faces at the top or bottom of the current collectors. In the figure below, they are plotted in red.

julia
components = [
    "NegativeCurrentCollector",
    "PositiveCurrentCollector"
]

for component in components
    plot_mesh!(ax, grids[component];
               boundaryfaces = couplings[component]["External"]["boundaryfaces"],
               color = :red)
end


ax.azimuth[] = 4.0
ax.elevation[] = 1.56

Simulation

We reload the original parameters

julia
cell_parameters     = load_cell_parameters(; from_default_set = "Chen2020")
cycling_protocol    = load_cycling_protocol(; from_default_set = "CCDischarge")
model_settings      = load_model_settings(; from_default_set = "P4D_cylindrical")
simulation_settings = load_simulation_settings(; from_default_set = "P4D_cylindrical")
{
    "GridResolution" =>     {
        "PositiveElectrodeCoating" => 3
        "Separator" => 3
        "NegativeElectrodeActiveMaterial" => 5
        "NegativeElectrodeCoating" => 3
        "NegativeElectrodeCurrentCollector" => 3
        "Angular" => 8
        "Height" => 2
        "PositiveElectrodeCurrentCollector" => 3
        "PositiveElectrodeCurrentCollectorTabWidth" => 2
        "PositiveElectrodeActiveMaterial" => 5
        "NegativeElectrodeCurrentCollectorTabWidth" => 2
    }
    "TimeStepDuration" => 50
    "RampUpTime" => 10
    "RampUpSteps" => 5
}

We adjust the parameters so that the simulation in this example is not too long (around a couple of minutes)

julia
cell_parameters["Cell"]["OuterRadius"] = 0.004
cell_parameters["NegativeElectrode"]["CurrentCollector"]["TabFractions"] = [0.5]
cell_parameters["PositiveElectrode"]["CurrentCollector"]["TabFractions"] = [0.5]
cell_parameters["NegativeElectrode"]["CurrentCollector"]["TabWidth"]     = 0.002
cell_parameters["PositiveElectrode"]["CurrentCollector"]["TabWidth"]     = 0.002
simulation_settings["GridResolution"]["Angular"] = 8
8

We setup the simulation and run it

julia
sim = Simulation(model_setup, cell_parameters, cycling_protocol; simulation_settings);
output = solve(sim; info_level = -1)
✔️ Validation of CellParameters passed: No issues found.
──────────────────────────────────────────────────
✔️ Validation of CyclingProtocol passed: No issues found.
──────────────────────────────────────────────────
✔️ Validation of SimulationSettings passed: No issues found.
──────────────────────────────────────────────────

Visualization of the simulation output

We plot the discharge curve

julia
states = output[:states]
model  = output[:extra][:model]

t = [state[:Control][:Controller].time for state in states]
E = [state[:Control][:Phi][1] for state in states]
I = [state[:Control][:Current][1] for state in states]

f = Figure(size = (1000, 400))

ax = Axis(f[1, 1],
	title = "Voltage",
	xlabel = "Time / s",
	ylabel = "Voltage / V",
	xlabelsize = 25,
	ylabelsize = 25,
	xticklabelsize = 25,
	yticklabelsize = 25)

scatterlines!(ax,
	t,
	E;
	linewidth = 4,
	markersize = 10,
	marker = :cross,
	markercolor = :black,
)

ax = Axis(f[1, 2],
	title = "Current",
	xlabel = "Time / s",
	ylabel = "Current / A",
	xlabelsize = 25,
	ylabelsize = 25,
	xticklabelsize = 25,
	yticklabelsize = 25,
)

scatterlines!(ax,
	t,
	I;
	linewidth = 4,
	markersize = 10,
	marker = :cross,
	markercolor = :black)

We open the interactive visualization tool with the simulation output.

julia
plot_interactive_3d(output; colormap = :curl)

Example on GitHub

If you would like to run this example yourself, it can be downloaded from the BattMo.jl GitHub repository as a script.


This page was generated using Literate.jl.