Intermediate usage
Setup a P4D Model using mergeJsonStructs
Let’s build a pseudo-four-dimensional Li-ion battery model and explore more about how to mix-and-match BattMo parameter definitions!
P4D simulations provide the most spatial detail for battery simulations. They can consider the effects of complex shapes like current collector tabs, jelly rolls, or multi-layer cells on overall performance. However, they are also the most computationally expensive simulations to run. They are therefore usually reserved for specicial cases when geometric effects play a significant role.
P4D models can be setup using a similar JSON parameter definition as described in the section on Basic Usage.
BattMo aims to provide a modular solution for building electrochemical models. That allows us to mix-and-match different sets of parameter definitions without needing to do much re-coding. In this example, we will use the mergeJsonStructs function to build a model definition from multiple sources.
Define Parameters
We will combine five separate JSON files that define the parameters for:
cell materials
cell geometry
control policy
simulation settings
output specifications
First, let’s define our cell materials. We have provided a JSON file that contains material properties for an NMC-Graphite Li-ion battery and can parse this as a BattMo structure:
jsonfilename = 'ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_graphite.json';
jsonstruct_material = parseBattmoJson(jsonfilename);
Next, we have defined the cell geometry properties in a separate JSON file that we can also parse into BattMo:
jsonfilename = 'Examples/jsondatafiles/geometry3d.json';
jsonstruct_geometry = parseBattmoJson(jsonfilename);
We can take the same approach for the remaining parameters, as shown below, for:
Control policy
jsonfilename = fullfile('Examples', 'jsondatafiles', 'ie_control.json');
jsonstruct_control = parseBattmoJson(jsonfilename);
Simulation settings
jsonfilename = fullfile('Examples', 'jsondatafiles', 'simulation_parameters.json');
jsonstruct_simparams = parseBattmoJson(jsonfilename);
Output specifications
jsonfilename = fullfile('Examples', 'jsondatafiles', 'extra_output.json');
jsonstruct_output = parseBattmoJson(jsonfilename);
We can now merge these parameter definitions into a single parameter set and run the simulation:
jsonstruct = mergeJsonStructs({jsonstruct_geometry , ...
jsonstruct_material , ...
jsonstruct_control , ...
jsonstruct_simparams, ...
jsonstruct_output , ...
});
Run Simulation
output = runBatteryJson(jsonstruct);
Visualize Results
We plot the model using plotBatteryGrid (note that the different axis are scaled differently)
model = output.model
plotBatteryGrid(model)
We find a extensive set of plotting functions in MRST. You may be interested to have a look at the Visualization Tutorial. Let us use the plotGrid and plotCellData to plot the surface particle concentrations in both electrode at a given time step.
state = output.states{20};
E = state.Control.E
plotGrid(model.grid, 'facecolor', 'none', 'edgealpha', 0.1)
plotCellData(model.NegativeElectrode.Coating.grid, state.NegativeElectrode.Coating.ActiveMaterial.SolidDiffusion.cSurface/(mol/litre))
plotCellData(model.PositiveElectrode.Coating.grid, state.PositiveElectrode.Coating.ActiveMaterial.SolidDiffusion.cSurface/(mol/litre))
title('Particle Surface Lithium Concentration');
File links and insertions with parseBattmoJson
There are two mechanisms which can be used to combine JSON input files:
Merge function using
mergeJsonStruct
Direct insertion using
parseBattmoJson
We have just seen an example of the first mechanism, which can be used within Matlab when we setup the simulation.
The function parseBattmoJson is used to parse a JSON input and create the corresponding matlab structure. It basically relies on jsondecode.
In this process the reserved keyword properties isFile
combined with filename
are used to fetch and
insert in place JSON data located in separate files. Here is an example, taken from
lithium_ion_battery_nmc_graphite.json
where we have the following lines
"NegativeElectrode": {
"Coating": {
"ActiveMaterial": {
"Interface": {
"isFile": true,
"filename": "ParameterData/MaterialProperties/Graphite/graphite.json"
}}}}
The content of the file graphite.json is then inserted in place. Hence, when we write
filename = fileread('ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_graphite.json')
jsonstruct = parseBattmoJson(filename)
the jsonstruct
that is obtained is equivalent to the one where we would have copied and paste the content of
graphite.json.
"NegativeElectrode": {
"Coating": {
"ActiveMaterial": {
"Interface": {
"saturationConcentration": 30555,
"volumetricSurfaceArea": 723600,
"density": 2240,
"numberOfElectronsTransferred" : 1,
"activationEnergyOfReaction": 5000,
"reactionRateConstant": 5.031e-11,
"guestStoichiometry100": 0.88551,
"guestStoichiometry0": 0.1429,
"chargeTransferCoefficient": 0.5,
"openCircuitPotential" : {"type": "function",
"functionname" : "computeOCP_graphite",
"argumentlist" : ["cElectrode", "T", "cmax"]
}}},