Tutorial 8 - Simulate a Multilayer Pouch Cell

Introduction

In this tutorial, we simulate a multilayer pouch cell. We use the same material property as in the other tutorials
jsonstruct_material = parseBattmoJson('Examples/jsondatafiles/sample_input.json');
Next, we load and parse a json file where we have chosen some parameters for the multilayer pouch domain. Note that all the parameters are described in a json schema, see Geometry.schema.json, even if the simplest way to proceed is to start with an example, in this case given by geometryMultiLayerPouch.json.
jsonfilename = 'Examples/JsonDataFiles/geometryMultiLayerPouch.json';
jsonstruct_geometry = parseBattmoJson(jsonfilename);
We use FlatJsonViewer.m to flatten the json structure and print it to screen. We can see that, in this example, we use 5 layers and two different lengths for the tabs (height value). At the moment, the two tabs share the same width. Implementing a separate width for each tab would require to modify the grid generator for this geometry. It is more a developer work but is definitely not out of reach.
fjv = flattenJson(jsonstruct_geometry)
fjv =
FlatJsonViewer with properties: flatjson: {23×2 cell} columnnames: {'parameter name' 'parameter value'}
fjv.print();
T = 23×2 table
 parameter nameparameter value
1'Geometry.case''multiLayerPouch'
2'Geometry.nLayers'5
3'Geometry.width'0.1000
4'Geometry.length'0.1000
5'Geometry.tab.width'0.0500
6'Geometry.tab.Nx'3
7'Geometry.tab.NegativeElectrode.length'0.0400
8'Geometry.tab.NegativeElectrode.Ny'2
9'Geometry.tab.PositiveElectrode.length'0.0200
10'Geometry.tab.PositiveElectrode.Ny'2
11'Geometry.Electrolyte.Nx'2
12'Geometry.Electrolyte.Ny'4
13'include_current_collectors'1
14'NegativeElectrode.Coating.thickness'1.0000e-04
We load and parse the control protocol like we did in tutorial_7,
jsonfilename = fullfile('Examples', 'jsondatafiles', 'cc_discharge_control.json');
jsonstruct_control = parseBattmoJson(jsonfilename);
We load and parse the simulation settings. This is optional. Typically, reasonable choices are made by default.
jsonfilename = fullfile('Examples', 'jsondatafiles', 'simulation_parameters.json');
jsonstruct_simparams = parseBattmoJson(jsonfilename);
Now, we can merge these parameter definitions into a single parameter set to obtain a jsonstruct that has all the input needed by the simulator.
jsonstruct = mergeJsonStructs({jsonstruct_geometry , ...
jsonstruct_material , ...
jsonstruct_control , ...
jsonstruct_simparams}, 'warn', false);

Setup the model for inspection

When we run the simulation using function runBatteryJson.m, the model is setup. In the case where we want to setup the model for inspection, prior to simulation, we can use the function setupModelFromJson.m
model = setupModelFromJson(jsonstruct);
We use the plotBatteryGrid.m function to show the grid
plotBatteryGrid(model)
% make the axis tight and set the camera viewing angle
axis tight
view(45,45)

Run the simulation

output = runBatteryJson(jsonstruct);
Solving timestep 01/45: -> 3 Seconds, 937 Milliseconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.493353e-16.
Solving timestep 02/45: 3 Seconds, 937 Milliseconds -> 7 Seconds, 875 Milliseconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.531088e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.590813e-16.
Solving timestep 03/45: 7 Seconds, 875 Milliseconds -> 15 Seconds, 750 Milliseconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.528465e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.477082e-16.
Solving timestep 04/45: 15 Seconds, 750 Milliseconds -> 31 Seconds, 500 Milliseconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.489881e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.476907e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.471405e-16.
Solving timestep 05/45: 31 Seconds, 500 Milliseconds -> 63 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.458264e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.443487e-16.
Solving timestep 06/45: 63 Seconds -> 126 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.450495e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.450321e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.443216e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.450676e-16.
Solving timestep 07/45: 126 Seconds -> 252 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.438794e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.437083e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.440133e-16.
Solving timestep 08/45: 252 Seconds -> 378 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 09/45: 378 Seconds -> 504 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 10/45: 504 Seconds -> 630 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 11/45: 630 Seconds -> 756 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 12/45: 756 Seconds -> 882 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 13/45: 882 Seconds -> 1008 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 14/45: 1008 Seconds -> 1134 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 15/45: 1134 Seconds -> 1260 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 16/45: 1260 Seconds -> 1386 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 17/45: 1386 Seconds -> 1512 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 18/45: 1512 Seconds -> 1638 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 19/45: 1638 Seconds -> 1764 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 20/45: 1764 Seconds -> 1890 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 21/45: 1890 Seconds -> 2016 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 22/45: 2016 Seconds -> 2142 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 23/45: 2142 Seconds -> 2268 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 24/45: 2268 Seconds -> 2394 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 25/45: 2394 Seconds -> 2520 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 26/45: 2520 Seconds -> 2646 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 27/45: 2646 Seconds -> 2772 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 28/45: 2772 Seconds -> 2898 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 29/45: 2898 Seconds -> 3024 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 30/45: 3024 Seconds -> 3150 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 31/45: 3150 Seconds -> 3276 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 32/45: 3276 Seconds -> 3402 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.434604e-16.
Solving timestep 33/45: 3402 Seconds -> 3528 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.436534e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.436534e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.439813e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.439813e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.440680e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.440680e-16.
Solving timestep 34/45: 3528 Seconds -> 1 Hour, 54 Seconds
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.447356e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.454802e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.467445e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.478529e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.487158e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.494945e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.502599e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.510373e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.518371e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.526639e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.535201e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.544071e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.553256e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.562763e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.572596e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.582761e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.593263e-16.
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.604111e-16.
*** Simulation complete. Solved 34 control steps in 9 Seconds, 759 Milliseconds (termination triggered by stopFunction) ***

Visualize the Results

Extract the time and voltage quantities
states = output.states;
 
time = cellfun(@(state) state.time, states);
voltage = cellfun(@(state) state.('Control').E, states);
We plot the discharge curves together in a new figure
figure();
plot((time/hour), voltage, '-', 'linewidth', 3)
xlabel('Time / h')
ylabel('Cell Voltage / V')
title('Voltage');
For a given time step, we plot the concentration on the grid.
% Set the timestep we want to visualize
timestep = 20;
 
% get the state of the simulation at the given timestep
state = states{timestep};
 
% create a new figure
figure()
 
% plot the surface concentration of lithium in the negative electrode active material
plotCellData(model.NegativeElectrode.Coating.grid, state.NegativeElectrode.Coating.ActiveMaterial.SolidDiffusion.cSurface/(mol/litre))
 
% plot the surface concentration of lithium in the positive electrode active material
plotCellData(model.PositiveElectrode.Coating.grid, state.PositiveElectrode.Coating.ActiveMaterial.SolidDiffusion.cSurface/(mol/litre))
 
title('Active Material Surface Lithium Concentration / mol \cdot L^{-1}');
% add a colorbar
colorbar()
view(45,45)