Skip to content

Selecting a model

As mentioned in the first tutorial, a model can be thought as a mathematical implementation of the electrochemical and transport phenomena occuring in a real battery cell. The implementation consist of a system of partial differential equations and their corresponding parameters, constants, boundary conditions and assumptions.

The default Lithium-Ion Battery Model corresponds to a basic P2D model, where neither current collectors, degradation nor thermal effects are considered. BattMo has implemented several variants of the Lithium-Ion Battery Model, which can be accessed by configuring the model object. In this tutorial, we’ll configure a P2D model with degradation driven by SEI (Solid Electrolyte Interphase) growth.

Load BattMo and Model Settings

julia
using BattMo, GLMakie

Let’s begin by loading the default model settings for a P2D simulation. This will return a ModelSettings object:

julia
model_settings = load_model_settings(; from_default_set = "P2D")

We can inspect all current settings with:

julia
model_settings.all
Dict{String, Any} with 4 entries:
  "RampUp"           => "Sinusoidal"
  "Metadata"         => {…
  "TransportInSolid" => "FullDiffusion"
  "ModelFramework"   => "P2D"

By default, the "SEIModel" parameter is set to false. Since we want to observe SEI-driven degradation effects, we’ll specify which SEI model we'd like to use, and with that enable the use of the SEI model during the simulation. Let's have a look at which models are available to include in the settings:

julia
print_submodels_info()
================================================================================
ℹ️  Submodels Information
================================================================================
Parameter                     Options                       Documentation
--------------------------------------------------------------------------------
CurrentCollectors             Generic                       -
SEIModel                      Bolay                         ]8;;https://battmoteam.github.io/BattMo.jl/dev/manuals/user_guide/sei_model\visit]8;;\
RampUp                        Sinusoidal                    ]8;;https://battmoteam.github.io/BattMo.jl/dev/manuals/user_guide/ramp_up\visit]8;;\
TransportInSolid              FullDiffusion                 -
ModelFramework                P2D, P4D Pouch, P4D Cylindrical]8;;https://battmoteam.github.io/BattMo.jl/dev/manuals/user_guide/pxd_model\visit]8;;\

For the SEI model, we can see there's one model to enable which is the "Bolay" model. We enable it in the model settings:

julia
model_settings["SEIModel"] = "Bolay"
model_settings.all
Dict{String, Any} with 5 entries:
  "SEIModel"         => "Bolay"
  "RampUp"           => "Sinusoidal"
  "Metadata"         => {…
  "TransportInSolid" => "FullDiffusion"
  "ModelFramework"   => "P2D"

Initialize the Model

Let’s now create the battery model using the modified settings:

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

When setting up the model, the LithiumIonBattery constructor runs a validation on the model_settings. In this case, because we set the "SEIModel" parameter to true, the validator provides a warning that we should define which SEI model we would like to use. If we ignore any warnings and pass the model to the Simulation constructor then we get an error. Let's create such a situation:

julia
model_settings["SEIModel"] = "Bola"


model_setup = LithiumIonBattery(; model_settings);
🔍 Validation of ModelSettings failed with 1 issue:

──────────────────────────────────────────────────
──────────────────────────────────────────────────
Issue 1:
📍 Where:       [SEIModel]
🔢 Provided:    Bola
🔑 Rule:        enum = ["Bolay"]
🛠  Issue:       Value must be one of: Bolay

──────────────────────────────────────────────────

We get a warning that a validation issue has been encountered. For now we ignore it:

julia
cell_parameters_sei = load_cell_parameters(; from_default_set = "Chen2020")
cccv_protocol = load_cycling_protocol(; from_default_set = "CCCV")

	sim = Simulation(model_setup, cell_parameters_sei, cccv_protocol)
Oops! Your Model object is not valid. 🛑

TIP: Validation happens when instantiating the Model object.
Check the warnings to see exactly where things went wrong. 🔍

As expected, this results in an error because we didn't specify the SEI model correctly.

Specify SEI Model and Rebuild

Let's resolve the issue again and run the simulation:

julia
model_settings["SEIModel"] = "Bolay"

Now rebuild the model:

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

Now we can setup the simulation and run it.

julia
sim = Simulation(model_setup, cell_parameters_sei, cccv_protocol)
output = solve(sim)
✔️ Validation of CellParameters passed: No issues found.
──────────────────────────────────────────────────
✔️ Validation of CyclingProtocol passed: No issues found.
──────────────────────────────────────────────────
✔️ Validation of SimulationSettings passed: No issues found.
──────────────────────────────────────────────────
Jutul: Simulating 15 hours as 1080 report steps
╭────────────────┬───────────┬───────────────┬────────────╮
 Iteration type   Avg/step   Avg/ministep       Total 
 794 steps  841 ministeps    (wasted) 
├────────────────┼───────────┼───────────────┼────────────┤
 Newton         │   2.85642 │       2.69679 │ 2268 (525) │
 Linearization  │   3.91436 │        3.6956 │ 3108 (551) │
 Linear solver  │   2.85642 │       2.69679 │ 2268 (525) │
 Precond apply  │       0.0 │           0.0 │      0 (0) │
╰────────────────┴───────────┴───────────────┴────────────╯
╭───────────────┬────────┬────────────┬────────╮
 Timing type      Each    Relative   Total 
     ms  Percentage       s 
├───────────────┼────────┼────────────┼────────┤
 Properties    │ 0.0420 │     2.13 % │ 0.0953 │
 Equations     │ 0.6336 │    44.03 % │ 1.9693 │
 Assembly      │ 0.0740 │     5.14 % │ 0.2300 │
 Linear solve  │ 0.5844 │    29.63 % │ 1.3254 │
 Linear setup  │ 0.0000 │     0.00 % │ 0.0000 │
 Precond apply │ 0.0000 │     0.00 % │ 0.0000 │
 Update        │ 0.0569 │     2.89 % │ 0.1291 │
 Convergence   │ 0.0746 │     5.18 % │ 0.2318 │
 Input/Output  │ 0.0231 │     0.43 % │ 0.0194 │
 Other         │ 0.2085 │    10.57 % │ 0.4728 │
├───────────────┼────────┼────────────┼────────┤
 Total         │ 1.9723 │   100.00 % │ 4.4731 │
╰───────────────┴────────┴────────────┴────────╯

Plot of voltage and current

julia
states = output[:states]

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,
	label = "Julia",
)

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,
	label = "Julia",
)

Plot of SEI length

We recover the SEI length from the state output

julia
seilength = [state[:NeAm][:SEIlength][end] for state in states]

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

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

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

ax = Axis(f[2, 1],
	title = "Length",
	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)

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.