{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "# Tutorial 7 \\- A Simple P4D Simulation\n", "\n", "## Introduction\n", "\n", "In this tutorial, we will use a simple P4D simulation to explore the effects of battery cell architecture. After completing this tutorial, you should have a working knowledge of:\n", "\n", "- How to setup and run a P4D simulation of a single cell in BattMo\n", "- Advanced usage of combining model descriptions from multiple sources\n", "## Construct the Model from Different Sources\n", "\n", "Let's say that you parameterize some cell materials and put that data in a JSON file. Then you get some description of your cell geometry, and you put that data in another JSON file. Now you want to combine those descriptions into a single model and simulate it using some pre\\-defined contol protocol and simulation settings in other files. How can we combine those easily, without having to do any recoding?\n", "\n", "\n", "To do that, we can simply make use of the mergeJsonStructs function in **BattMo**.\n", "\n", "\n", "First, let’s define our cell materials. We have provided a JSON file that contains material properties for a NMC and Graphite active materials, which we can parse as a **BattMo** structure:\n", "" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "source": [ "% parse material definitions as a BattMo structure\n", "jsonfilename = 'ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_graphite.json';\n", "jsonstruct_material = parseBattmoJson(jsonfilename);" ], "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Next, we have defined the cell geometry properties in a separate JSON file that we can also parse into **BattMo**:\n", "" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "source": [ "% parse cell geometry specifications as a BattMo structure\n", "jsonfilename = 'Examples/jsondatafiles/geometry3d.json';\n", "jsonstruct_geometry = parseBattmoJson(jsonfilename);" ], "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Let's have a closer look at the cell geometry specification.\n", "" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "source": [ "disp(jsonstruct_geometry.Geometry)" ], "outputs": [ { "data": { "text/plain": [ " case: '3D-demo'\n", " width: 0.0100\n", " height: 0.0200\n", " Nw: 10\n", " Nh: 10" ] }, "metadata": {}, "execution_count": 3, "output_type": "execute_result" } ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Here we can see that the width and height dimensions of the cell are defined, along with the number of discretizations in each direction, and a case description. The case sets the type of simulation to be performed. Here it is set to '3D\\-demo', to BattMo knows to setp a P4D mesh.\n", "\n", "\n", "We can take the same approach for the remaining parameters, as shown below, for the control protocol, simulation settings, and output settings:\n", "" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "source": [ "% control protocol\n", "jsonfilename = fullfile('Examples', 'jsondatafiles', 'cc_discharge_control.json');\n", "jsonstruct_control = parseBattmoJson(jsonfilename);\n", "\n", "% simulation settings\n", "jsonfilename = fullfile('Examples', 'jsondatafiles', 'simulation_parameters.json');\n", "jsonstruct_simparams = parseBattmoJson(jsonfilename);\n", "\n", "% output settings\n", "jsonfilename = fullfile('Examples', 'jsondatafiles', 'extra_output.json');\n", "jsonstruct_output = parseBattmoJson(jsonfilename);" ], "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Now, we can merge these parameter definitions into a single parameter set and run the simulation:\n", "" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "source": [ "% combine the parameter structures from the different sources into a single\n", "% BattMo structure\n", "jsonstruct = mergeJsonStructs({jsonstruct_geometry , ...\n", " jsonstruct_material , ...\n", " jsonstruct_control , ...\n", " jsonstruct_simparams, ...\n", " jsonstruct_output , ...\n", " });" ], "outputs": [ { "data": { "text/plain": [ "mergeJsonStructs: Parameter include_current_collectors is assigned twice with different values. Value from first jsonstruct is used.\n", "mergeJsonStructs: Parameter ThermalModel.externalHeatTransferCoefficient is assigned twice with different values. Value from first jsonstruct is used." ] }, "metadata": {}, "execution_count": 5, "output_type": "execute_result" } ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "we store the output as a cell array so we can compare results across different simulation runs in this tutorial; here we instantiate an empty cell array\n", "" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "source": [ "output = cell(2,1);\n", "\n", "% run the simulation\n", "output{1} = runBatteryJson(jsonstruct);" ], "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualize the Results\n", "\n", "We plot the model using [plotBatteryGrid](https://github.com/BattMoTeam/BattMo/blob/main/Utilities/Visualization/plotBatteryGrid.m) (note that the different axis are scaled differently)\n", "" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "source": [ "% create a shorthand variable for the model\n", "model = output{1}.model;\n", "\n", "% use the plotBatteryGrid function to show the grid\n", "plotBatteryGrid(model)" ], "outputs": [ { "data": { "text/plain": [ "ans = \n", " Figure (10) with properties:\n", " Number: 10\n", " Name: ''\n", " Color: [1 1 1]\n", " Position: [1411 753 618 463]\n", " Units: 'pixels'\n", " Use GET to show all properties" ] }, "metadata": {}, "execution_count": 7, "output_type": "execute_result" } ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "source": [ "\n", "% make the axis tight and set the camera viewing angle\n", "axis tight\n", "view(45,45)" ], "outputs": [ { "data": { "text/html": [ "
\"figure_0.png\"
" ] }, "metadata": {}, "execution_count": 8, "output_type": "execute_result" } ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "We find a extensive set of plotting functions in [MRST](https://www.sintef.no/Projectweb/MRST/). You may be interested to have a look at the [Visualization Tutorial](https://www.sintef.no/projectweb/mrst/documentation/tutorials/visualization-tutorial/). Let us use the [plotGrid](https://github.com/SINTEF-AppliedCompSci/MRST/blob/main/core/plotting/plotGrid.m) and [plotCellData](https://github.com/SINTEF-AppliedCompSci/MRST/blob/main/core/plotting/plotCellData.m) to plot the surface particle concentrations in both electrode at a given time step.\n", "" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "source": [ "% set the timestep we want to visualize\n", "timestep = 20;\n", "\n", "% get the state of the simulation at the given timestep\n", "state = output{1}.states{timestep};\n", "\n", "% create a new figure\n", "figure()\n", "\n", "% plot the surface concentration of lithium in the negative electrode active material\n", "plotCellData(model.NegativeElectrode.Coating.grid, state.NegativeElectrode.Coating.ActiveMaterial.SolidDiffusion.cSurface/(mol/litre))\n", "\n", "% plot the surface concentration of lithium in the positive electrode active material\n", "plotCellData(model.PositiveElectrode.Coating.grid, state.PositiveElectrode.Coating.ActiveMaterial.SolidDiffusion.cSurface/(mol/litre))\n", "\n", "% add a colorbar\n", "colorbar()\n", "\n", "% make the axis tight and set the camera viewing angle\n", "axis tight\n", "view(45,45)\n", "\n", "% add plot annotations\n", "title('Active Material Surface Lithium Concentration / mol \\cdot L^{-1}');" ], "outputs": [ { "data": { "text/html": [ "
\"figure_1.png\"
" ] }, "metadata": {}, "execution_count": 9, "output_type": "execute_result" } ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compare with a P2D Simulation" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "source": [ "% change the setup of the model to consider a P2D case\n", "jsonstruct.Geometry.case = '1D';\n", "jsonstruct.Geometry.faceArea = jsonstruct.Geometry.width * jsonstruct.Geometry.height;\n", "\n", "% change the rate\n", "jsonstruct.Control.CRate = 1;\n", "\n", "% update the total time of the simulation\n", "jsonstruct.TimeStepping.totalTime = (1./jsonstruct.Control.CRate) .* 3600 .* 1.1;\n", "\n", "% run the simulation\n", "output{2} = runBatteryJson(jsonstruct);" ], "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "In this case, MATLAB sends many warnings about the ill\\-conditionness of the system. The ill\\-conditionness appears to come mainly from the very high ratio between the electronic conductivity of the current collectors and the other components.\n", "" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "source": [ "% get the states from the P2D model\n", "states_P2D = output{2}.states;\n", "\n", "% extract the time and voltage quantities\n", "time_P2D = cellfun(@(state) state.time, states_P2D);\n", "voltage_P2D = cellfun(@(state) state.('Control').E, states_P2D);\n", "\n", "% get the states from the P4D model\n", "states_P4D = output{1}.states;\n", "\n", "% extract the time and voltage quantities\n", "time_P4D = cellfun(@(state) state.time, states_P4D);\n", "voltage_P4D = cellfun(@(state) state.('Control').E, states_P4D);\n", "\n", "% plot the discharge curves together in a new figure\n", "figure();\n", "plot((time_P2D/hour), voltage_P2D, '-', 'linewidth', 3)\n", "hold on\n", "plot((time_P4D/hour), voltage_P4D, '-', 'linewidth', 3)\n", "xlabel('Time / h')\n", "ylabel('Cell Voltage / V')\n", "legend('P2D', 'P4D')" ], "outputs": [ { "data": { "text/html": [ "
\"figure_2.png\"
" ] }, "metadata": {}, "execution_count": 11, "output_type": "execute_result" } ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "\n", "In this tutorial, we learned how to create a simple P4D simulation in BattMo. First, we explored how to combine parameter sets coming from a handful of different files into a single coherent BattMo model description. Then we had a closer look into the Geometry description to see how BattMo knows how to setup a P4D or P2D type model. After running the P4D simulation, we learned how to visualize simulation results on a 3D grid. For comparison, we ran the same model in a P2D configuration and plotted the discharge curves together. This showed that the results can diverge somewhat due to the effects of the tabs and non\\-ideal transport in the electrode plane. These results show that P4D models can yield important insight that may be lost in the averaged approach of P2D models.\n", "\n", "" ] } ], "metadata": { "kernelspec": { "display_name": "MATLAB (matlabkernel)", "language": "matlab", "name": "matlab" }, "language_info": { "file_extension": ".m", "mimetype": "text/matlab", "name": "matlab", "nbconvert_exporter": "matlab", "pygments_lexer": "matlab", "version": "24.1.0.2689473" } }, "nbformat": 4, "nbformat_minor": 4 }