diff --git a/_images/runBatteryP2D_01.png b/_images/runBatteryP2D_01.png index 4239be97..449739ff 100644 Binary files a/_images/runBatteryP2D_01.png and b/_images/runBatteryP2D_01.png differ diff --git a/_images/runElectrolyser_02.png b/_images/runElectrolyser_02.png deleted file mode 100644 index 55f766d1..00000000 Binary files a/_images/runElectrolyser_02.png and /dev/null differ diff --git a/_images/runGasSupply_01.png b/_images/runGasSupply_01.png index d657e803..ee590c05 100644 Binary files a/_images/runGasSupply_01.png and b/_images/runGasSupply_01.png differ diff --git a/_images/runGasSupply_02.png b/_images/runGasSupply_02.png index ca63a6f5..a2f07a50 100644 Binary files a/_images/runGasSupply_02.png and b/_images/runGasSupply_02.png differ diff --git a/_images/runGasSupply_03.png b/_images/runGasSupply_03.png index 82b50d50..a63ccbe3 100644 Binary files a/_images/runGasSupply_03.png and b/_images/runGasSupply_03.png differ diff --git a/_images/runGasSupply_04.png b/_images/runGasSupply_04.png index d2e6734b..a8f9bc49 100644 Binary files a/_images/runGasSupply_04.png and b/_images/runGasSupply_04.png differ diff --git a/_images/runGasSupply_05.png b/_images/runGasSupply_05.png index bb15b47d..83579269 100644 Binary files a/_images/runGasSupply_05.png and b/_images/runGasSupply_05.png differ diff --git a/_images/runGasSupply_06.png b/_images/runGasSupply_06.png index 75c02525..ce7b4304 100644 Binary files a/_images/runGasSupply_06.png and b/_images/runGasSupply_06.png differ diff --git a/_images/runGasSupply_07.png b/_images/runGasSupply_07.png index b964a88a..ee87492d 100644 Binary files a/_images/runGasSupply_07.png and b/_images/runGasSupply_07.png differ diff --git a/_images/runGasSupply_08.png b/_images/runGasSupply_08.png index 8c695b4b..73028eae 100644 Binary files a/_images/runGasSupply_08.png and b/_images/runGasSupply_08.png differ diff --git a/_images/runGasSupply_09.png b/_images/runGasSupply_09.png index 42a1a558..722ddc26 100644 Binary files a/_images/runGasSupply_09.png and b/_images/runGasSupply_09.png differ diff --git a/_images/runProtonicCell_01.png b/_images/runProtonicCell_01.png new file mode 100644 index 00000000..f668acc7 Binary files /dev/null and b/_images/runProtonicCell_01.png differ diff --git a/_images/runProtonicCell_02.png b/_images/runProtonicCell_02.png new file mode 100644 index 00000000..c5a3fffd Binary files /dev/null and b/_images/runProtonicCell_02.png differ diff --git a/_images/runProtonicCell_03.png b/_images/runProtonicCell_03.png new file mode 100644 index 00000000..b0fb15e2 Binary files /dev/null and b/_images/runProtonicCell_03.png differ diff --git a/_images/runProtonicCell_04.png b/_images/runProtonicCell_04.png new file mode 100644 index 00000000..a745ad59 Binary files /dev/null and b/_images/runProtonicCell_04.png differ diff --git a/_images/runProtonicCell_05.png b/_images/runProtonicCell_05.png new file mode 100644 index 00000000..18e4832a Binary files /dev/null and b/_images/runProtonicCell_05.png differ diff --git a/_images/runProtonicCell_06.png b/_images/runProtonicCell_06.png new file mode 100644 index 00000000..9aa912a5 Binary files /dev/null and b/_images/runProtonicCell_06.png differ diff --git a/_images/runProtonicCell_07.png b/_images/runProtonicCell_07.png new file mode 100644 index 00000000..3b8b3152 Binary files /dev/null and b/_images/runProtonicCell_07.png differ diff --git a/_images/runProtonicCell_08.png b/_images/runProtonicCell_08.png new file mode 100644 index 00000000..db25d413 Binary files /dev/null and b/_images/runProtonicCell_08.png differ diff --git a/_images/runProtonicCell_09.png b/_images/runProtonicCell_09.png new file mode 100644 index 00000000..4a59b2fa Binary files /dev/null and b/_images/runProtonicCell_09.png differ diff --git a/_images/runProtonicCell_10.png b/_images/runProtonicCell_10.png new file mode 100644 index 00000000..8f8e2792 Binary files /dev/null and b/_images/runProtonicCell_10.png differ diff --git a/_images/runProtonicCell_11.png b/_images/runProtonicCell_11.png new file mode 100644 index 00000000..e8af335a Binary files /dev/null and b/_images/runProtonicCell_11.png differ diff --git a/_images/runProtonicCell_12.png b/_images/runProtonicCell_12.png new file mode 100644 index 00000000..60955e17 Binary files /dev/null and b/_images/runProtonicCell_12.png differ diff --git a/_images/runProtonicCell_13.png b/_images/runProtonicCell_13.png new file mode 100644 index 00000000..73a7968c Binary files /dev/null and b/_images/runProtonicCell_13.png differ diff --git a/_images/runProtonicMembrane_01.png b/_images/runProtonicMembrane_01.png index 1a2f4c9e..be45a088 100644 Binary files a/_images/runProtonicMembrane_01.png and b/_images/runProtonicMembrane_01.png differ diff --git a/_images/runProtonicMembrane_02.png b/_images/runProtonicMembrane_02.png index c8471434..0c62e24e 100644 Binary files a/_images/runProtonicMembrane_02.png and b/_images/runProtonicMembrane_02.png differ diff --git a/_images/runProtonicMembrane_03.png b/_images/runProtonicMembrane_03.png index 151d42ef..f1bcb96e 100644 Binary files a/_images/runProtonicMembrane_03.png and b/_images/runProtonicMembrane_03.png differ diff --git a/_images/runProtonicMembrane_04.png b/_images/runProtonicMembrane_04.png index 23bd8e93..46cd6a70 100644 Binary files a/_images/runProtonicMembrane_04.png and b/_images/runProtonicMembrane_04.png differ diff --git a/_images/runProtonicMembrane_05.png b/_images/runProtonicMembrane_05.png index a63825a6..98e28106 100644 Binary files a/_images/runProtonicMembrane_05.png and b/_images/runProtonicMembrane_05.png differ diff --git a/_images/runProtonicMembrane_06.png b/_images/runProtonicMembrane_06.png index 71994ae4..35f84a06 100644 Binary files a/_images/runProtonicMembrane_06.png and b/_images/runProtonicMembrane_06.png differ diff --git a/_images/runProtonicMembrane_07.png b/_images/runProtonicMembrane_07.png index d55e81ab..f703e27b 100644 Binary files a/_images/runProtonicMembrane_07.png and b/_images/runProtonicMembrane_07.png differ diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt index e5d99c58..fcf3a53f 100644 --- a/_sources/index.rst.txt +++ b/_sources/index.rst.txt @@ -15,8 +15,7 @@ advancedtopics juliabridge Electrolyser simulation - Protonic Membrane - Gas Supply + protonicmembrane app Computational Graph seealso diff --git a/_sources/protonicmembrane.rst.txt b/_sources/protonicmembrane.rst.txt new file mode 100644 index 00000000..ecee237d --- /dev/null +++ b/_sources/protonicmembrane.rst.txt @@ -0,0 +1,30 @@ +================= +Protonic Membrane +================= + +.. toctree:: + :hidden: + + Protonic Membrane + Gas Supply + Full Cell + +We consider the model of a mixed proton and electron conducting membrane, as described in :cite:`V_llestad_2019` from 2019. + +.. grid:: 1 + + .. grid-item-card:: + :padding: 2 + + :ref:`Protonic Membrane ` + + .. grid-item-card:: + :padding: 2 + + :ref:`Gas Supply Layer ` + + .. grid-item-card:: + :padding: 2 + + :ref:`Full Cell ` + diff --git a/_sources/publishedExamples/battMoTutorial.rst.txt b/_sources/publishedExamples/battMoTutorial.rst.txt index 90835a5c..c315dcce 100644 --- a/_sources/publishedExamples/battMoTutorial.rst.txt +++ b/_sources/publishedExamples/battMoTutorial.rst.txt @@ -32,7 +32,7 @@ BattMo uses functionality from :mod:`MRST `. This functionality is c Specifying the physical model ============================= -In this tutorial we will simulate a lithium-ion battery consisting of a negative electrode, a positive electrode and an electrolyte. BattMo comes with some pre-defined models which can be loaded from JSON files. Here we will load the basic lithium-ion model JSON file which comes with Battmo. We use :battmo:`parseBattmoJson` to parse the file, see :todo:`add link to doc` +In this tutorial we will simulate a lithium-ion battery consisting of a negative electrode, a positive electrode and an electrolyte. BattMo comes with some pre-defined models which can be loaded from JSON files. Here we will load the basic lithium-ion model JSON file which comes with Battmo. We use :battmo:`parseBattmoJson` to parse the file. .. code-block:: matlab @@ -75,22 +75,22 @@ Now we can set the diffusion model type for the active material (am) in the posi jsonstruct.(pe).(am).diffusionModelType = 'full'; jsonstruct.(ne).(am).diffusionModelType = 'full'; -To see which other types of diffusion model are available one can view :battmo:`ActiveMaterialInputParams`. When running a simulation, BattMo requires that all model parameters are stored in an instance of :battmo:`BatteryInputParams`. This class is used to initialize the simulation and is accessed by various parts of the simulator during the simulation. This class is instantiated using the jsonstruct we just created: +To see which other types of diffusion model are available one can view :battmo:`ActiveMaterialInputParams`. When running a simulation, BattMo requires that all model parameters are stored in an instance of :battmo:`BatteryInputParams`. This class is used to initialize the simulation and is accessed by various parts of the simulator during the simulation. This class is instantiated using the jsonstruct we just created: .. code-block:: matlab - paramobj = BatteryInputParams(jsonstruct); + inputparams = BatteryInputParams(jsonstruct); -It is also possible to update the properties of this paramobj in a similar way to updating the jsonstruct. Here we set the discretisation level for the diffusion model. Other input parameters for the full diffusion model can be found here: :battmo:`FullSolidDiffusionModelInputParams`. +It is also possible to update the properties of this inputparams in a similar way to updating the jsonstruct. Here we set the discretisation level for the diffusion model. Other input parameters for the full diffusion model can be found here: :battmo:`FullSolidDiffusionModelInputParams`. .. code-block:: matlab - paramobj.(ne).(co).(am).(sd).N = 5; - paramobj.(pe).(co).(am).(sd).N = 5; + inputparams.(ne).(co).(am).(sd).N = 5; + inputparams.(pe).(co).(am).(sd).N = 5; % We can also change how the battery is operated, for example setting % the cut off voltage. - paramobj.(ctrl).lowerCutoffVoltage = 2.5; + inputparams.(ctrl).lowerCutoffVoltage = 2.5; Setting up the geometry @@ -101,21 +101,21 @@ Here, we setup the 1D computational grid that will be used for the simulation. T gen = BatteryGeneratorP2D(); -Now, we update the paramobj with the properties of the grid. This function will update relevent parameters in the paramobj object and make sure we have all the required parameters for the model geometry chosen. +Now, we update the inputparams with the properties of the grid. This function will update relevent parameters in the inputparams object and make sure we have all the required parameters for the model geometry chosen. .. code-block:: matlab - paramobj = gen.updateBatteryInputParams(paramobj); + inputparams = gen.updateBatteryInputParams(inputparams); Initialising the battery model object ===================================== -The battery model is initialized by sending paramobj to the Battery class constructor. see :battmo:`Battery`. +The battery model is initialized by sending inputparams to the Battery class constructor. see :battmo:`Battery`. In BattMo a battery model is actually a collection of submodels: Electrolyte, Negative Electrode, Positive Electrode, Thermal Model and Control Model. The battery class contains all of these submodels and various other parameters necessary to run the simulation. .. code-block:: matlab - model = Battery(paramobj); + model = Battery(inputparams); Plotting the OCP curves against state of charge @@ -158,22 +158,11 @@ We can inspect the model object to find out which parameters are being used. For Controlling the simulation ========================== The control model specifies how the battery is operated, i.e., how the simulation is controlled. -In the first instance we use CCDischarge control policy. We set the total time scaled by the CRate in the model. The CRate has been set by the json file. We can access it here: +The input parameters for the control have been given as part of the json structure :battmofile:`ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_graphite.json`. The total simulation time is setup for us, computed from the DRate value. We use the method :code:`setupScheduleStep` in :battmo:`ControlModel` to setup the :code:`step` structure. .. code-block:: matlab - CRate = model.Control.CRate; - total = 1.1*hour/CRate; - -We want to break this total time into 100 timesteps. To begin with we will use equal values for each timestep. -We create a structure containing the length of each step in seconds ('val') and also which control to use for each step ('control'). -In this case we use control 1 for all steps. This means that the functions used to setup the control values are the same at each step. - -.. code-block:: matlab - - n = 100; - dt = total/n; - step = struct('val', dt*ones(n, 1), 'control', ones(n, 1)); + step = model.Control.setupScheduleStep(); We create a control structure containing the source function and and a stopping criteria. The control parameters have been given in the json file :battmofile:`ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_graphite.json` The :code:`setupScheduleControl` method contains the code to setup the control structure that is used in the schedule structure setup below. @@ -201,7 +190,7 @@ To run simulation we need to know the starting point which we will run it from, Running the simulation ====================== Once we have the initial state, the model and the schedule, we can call the simulateScheduleAD function which will actually run the simulation. -The outputs from the simulation are: - sols: which provides the current and voltage of the battery at each timestep. - states: which contains the values of the primary variables in the model at each timestep. - reports: which contains technical information about the steps used in the numerical solvers. +The outputs from the simulation are: - sols: which provides the current and voltage of the battery at each timestep. - states: which contains the values of the primary variables in the model at each timestep. - reports: which contains technical information about the steps used in the numerical solvers. .. code-block:: matlab @@ -227,7 +216,6 @@ To get the results we use the matlab cellfun function to extract the values Cont subplot(1,2,2) plot(time/hour, I) - ylim([0, 0.02]) xlabel('time / h') ylabel('Cell Current / A') diff --git a/_sources/publishedExamples/battMoTutorial_source.rst.txt b/_sources/publishedExamples/battMoTutorial_source.rst.txt index 970731e0..5f1731e1 100644 --- a/_sources/publishedExamples/battMoTutorial_source.rst.txt +++ b/_sources/publishedExamples/battMoTutorial_source.rst.txt @@ -33,7 +33,7 @@ Source code for battMoTutorial % negative electrode, a positive electrode and an electrolyte. *BattMo* % comes with some pre-defined models which can be loaded from JSON files. % Here we will load the basic lithium-ion model JSON file which comes with - % Battmo. We use :battmo:`parseBattmoJson` to parse the file, see :todo:`add link to doc` + % Battmo. We use :battmo:`parseBattmoJson` to parse the file. fname = fullfile('ParameterData','BatteryCellParameters',... 'LithiumIonBatteryCell','lithium_ion_battery_nmc_graphite.json'); @@ -86,21 +86,21 @@ Source code for battMoTutorial % various parts of the simulator during the simulation. This class is % instantiated using the jsonstruct we just created: - paramobj = BatteryInputParams(jsonstruct); + inputparams = BatteryInputParams(jsonstruct); %% - % It is also possible to update the properties of this paramobj in a + % It is also possible to update the properties of this inputparams in a % similar way to updating the jsonstruct. Here we set the discretisation % level for the diffusion model. Other input parameters for the full diffusion % model can be found here: % :battmo:`FullSolidDiffusionModelInputParams`. - paramobj.(ne).(co).(am).(sd).N = 5; - paramobj.(pe).(co).(am).(sd).N = 5; + inputparams.(ne).(co).(am).(sd).N = 5; + inputparams.(pe).(co).(am).(sd).N = 5; % We can also change how the battery is operated, for example setting % the cut off voltage. - paramobj.(ctrl).lowerCutoffVoltage = 2.5; + inputparams.(ctrl).lowerCutoffVoltage = 2.5; %% Setting up the geometry % Here, we setup the 1D computational grid that will be used for the @@ -111,14 +111,14 @@ Source code for battMoTutorial gen = BatteryGeneratorP2D(); %% - % Now, we update the paramobj with the properties of the grid. This function - % will update relevent parameters in the paramobj object and make sure we have + % Now, we update the inputparams with the properties of the grid. This function + % will update relevent parameters in the inputparams object and make sure we have % all the required parameters for the model geometry chosen. - paramobj = gen.updateBatteryInputParams(paramobj); + inputparams = gen.updateBatteryInputParams(inputparams); %% Initialising the battery model object - % The battery model is initialized by sending paramobj to the Battery class + % The battery model is initialized by sending inputparams to the Battery class % constructor. see :battmo:`Battery`. % % In BattMo a battery model is actually a collection of submodels: @@ -126,7 +126,7 @@ Source code for battMoTutorial % Model. The battery class contains all of these submodels and various other % parameters necessary to run the simulation. - model = Battery(paramobj); + model = Battery(inputparams); %% Plotting the OCP curves against state of charge % We can inspect the model object to find out which parameters are being @@ -162,36 +162,22 @@ Source code for battMoTutorial legend(eldes, 'location', 'nw') %% Controlling the simulation - % The control model specifies how the battery is operated, i.e., how - % the simulation is controlled. + % The control model specifies how the battery is operated, i.e., how the simulation is controlled. % - % In the first instance we use CCDischarge control policy. - % We set the total time scaled by the CRate in the model. - % The CRate has been set by the json file. We can access it here: + % The input parameters for the control have been given as part of the json structure + % :battmofile:`ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_graphite.json`. The + % total simulation time is setup for us, computed from the DRate value. We use the method :code:`setupScheduleStep` in + % :battmo:`ControlModel` to setup the :code:`step` structure. - CRate = model.Control.CRate; - total = 1.1*hour/CRate; - - %% - % We want to break this total time into 100 timesteps. To begin with we - % will use equal values for each timestep. - % - % We create a structure containing the length of each step in seconds - % ('val') and also which control to use for each step ('control'). - % - % In this case we use control 1 for all steps. This means that the functions - % used to setup the control values are the same at each step. - - n = 100; - dt = total/n; - step = struct('val', dt*ones(n, 1), 'control', ones(n, 1)); + step = model.Control.setupScheduleStep(); %% % We create a control structure containing the source function and % and a stopping criteria. The control parameters have been given in the json file % :battmofile:`ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_graphite.json` % - % The :code:`setupScheduleControl` method contains the code to setup the control structure that is used in the schedule structure setup below. + % The :code:`setupScheduleControl` method contains the code to setup the control structure that is used in the schedule + % structure setup below. control = model.Control.setupScheduleControl(); @@ -212,7 +198,6 @@ Source code for battMoTutorial initstate = model.setupInitialState(); - %% Running the simulation % Once we have the initial state, the model and the schedule, we can call % the simulateScheduleAD function which will actually run the simulation. @@ -246,13 +231,12 @@ Source code for battMoTutorial subplot(1,2,2) plot(time/hour, I) - ylim([0, 0.02]) xlabel('time / h') ylabel('Cell Current / A') %{ - Copyright 2021-2023 SINTEF Industry, Sustainable Energy Technology + Copyright 2021-2024 SINTEF Industry, Sustainable Energy Technology and SINTEF Digital, Mathematics & Cybernetics. This file is part of The Battery Modeling Toolbox BattMo diff --git a/_sources/publishedExamples/runBatteryP2D.rst.txt b/_sources/publishedExamples/runBatteryP2D.rst.txt index 6823d3c7..e811613c 100644 --- a/_sources/publishedExamples/runBatteryP2D.rst.txt +++ b/_sources/publishedExamples/runBatteryP2D.rst.txt @@ -27,7 +27,7 @@ load MRST modules Setup the properties of Li-ion battery materials and cell design ================================================================ -The properties and parameters of the battery cell, including the architecture and materials, are set using an instance of :class:`BatteryInputParams `. This class is used to initialize the simulation and it propagates all the parameters throughout the submodels. The input parameters can be set manually or provided in json format. All the parameters for the model are stored in the paramobj object. +The properties and parameters of the battery cell, including the architecture and materials, are set using an instance of :class:`BatteryInputParams `. This class is used to initialize the simulation and it propagates all the parameters throughout the submodels. The input parameters can be set manually or provided in json format. All the parameters for the model are stored in the inputparams object. .. code-block:: matlab @@ -48,19 +48,22 @@ The properties and parameters of the battery cell, including the architecture an jsonstruct.use_thermal = false; jsonstruct.include_current_collectors = false; - paramobj = BatteryInputParams(jsonstruct); + inputparams = BatteryInputParams(jsonstruct); - use_cccv = false; + use_cccv = true; if use_cccv - cccvstruct = struct( 'controlPolicy' , 'CCCV', ... - 'initialControl' , 'discharging', ... - 'CRate' , 1 , ... - 'lowerCutoffVoltage', 2.4 , ... - 'upperCutoffVoltage', 4.1 , ... - 'dIdtLimit' , 0.01 , ... - 'dEdtLimit' , 0.01); - cccvparamobj = CcCvControlModelInputParams(cccvstruct); - paramobj.Control = cccvparamobj; + inputparams.SOC = 0; + cccvstruct = struct( 'controlPolicy' , 'CCCV' , ... + 'initialControl' , 'charging', ... + 'numberOfCycles' , 2 , ... + 'CRate' , 1.5 , ... + 'DRate' , 1 , ... + 'lowerCutoffVoltage', 3 , ... + 'upperCutoffVoltage', 4 , ... + 'dIdtLimit' , 1e-2 , ... + 'dEdtLimit' , 1e-4); + cccvinputparams = CcCvControlModelInputParams(cccvstruct); + inputparams.Control = cccvinputparams; end @@ -72,19 +75,17 @@ Here, we setup the 1D computational grid that will be used for the simulation. T gen = BatteryGeneratorP2D(); - % Now, we update the paramobj with the properties of the grid. - paramobj = gen.updateBatteryInputParams(paramobj); + % Now, we update the inputparams with the properties of the grid. + inputparams = gen.updateBatteryInputParams(inputparams); Initialize the battery model. ============================= -The battery model is initialized by sending paramobj to the Battery class constructor. see :class:`Battery `. +The battery model is initialized by sending inputparams to the Battery class constructor. see :class:`Battery `. .. code-block:: matlab - model = Battery(paramobj); - - model.AutoDiffBackend= AutoDiffBackend(); + model = GenericBattery(inputparams); inspectgraph = false; if inspectgraph @@ -93,36 +94,14 @@ The battery model is initialized by sending paramobj to the Battery class constr end -Compute the nominal cell capacity and choose a C-Rate -===================================================== -The nominal capacity of the cell is calculated from the active materials. This value is then combined with the user-defined C-Rate to set the cell operational current. - -.. code-block:: matlab - - CRate = model.Control.CRate; - - -Setup the time step schedule -============================ -Smaller time steps are used to ramp up the current from zero to its operational value. Larger time steps are then used for the normal operation. +Setup the schedule +================== .. code-block:: matlab - switch model.(ctrl).controlPolicy - case 'CCCV' - total = 3.5*hour/CRate; - case 'CCDischarge' - total = 1.4*hour/CRate; - otherwise - error('control policy not recognized'); - end - - n = 100; - dt = total/n; - step = struct('val', dt*ones(n, 1), 'control', ones(n, 1)); - - % we setup the control by assigning a source and stop function. + timestep.timeStepDuration = 100; + step = model.Control.setupScheduleStep(timestep); control = model.Control.setupScheduleControl(); % This control is used to set up the schedule @@ -170,9 +149,16 @@ Setup the properties of the nonlinear solver nls.maxIterations = 10; % Change default behavior of nonlinear solver, in case of error nls.errorOnFailure = false; - nls.timeStepSelector = StateChangeTimeStepSelector('TargetProps', {{'Control','E'}}, 'targetChangeAbs', 0.03); + % nls.timeStepSelector = StateChangeTimeStepSelector('TargetProps', {{'Control','E'}}, 'targetChangeAbs', 0.03); % Change default tolerance for nonlinear solver - model.nonlinearTolerance = 1e-3*model.Control.Imax; + nls.maxTimestepCuts = 6; + + if use_cccv + Imax = (model.(ctrl).ImaxDischarge + model.(ctrl).ImaxCharge); + else + Imax = model.(ctrl).Imax; + end + model.nonlinearTolerance = 1e-6*Imax; % Set verbosity model.verbose = true; @@ -200,11 +186,17 @@ Process output and recover the output voltage and current from the output states time = cellfun(@(x) x.time, states); figure - plot(time/hour, E); + plot(time/hour, E, '*-'); grid on xlabel 'time / h'; ylabel 'potential / V'; + figure + plot(time/hour, I, '*-'); + grid on + xlabel 'time / h'; + ylabel 'Current / A'; + writeh5 = false; if writeh5 writeOutput(model, states, 'output.h5'); @@ -213,6 +205,9 @@ Process output and recover the output voltage and current from the output states .. figure:: runBatteryP2D_01.png :figwidth: 100% +.. figure:: runBatteryP2D_02.png + :figwidth: 100% + complete source code can be found :ref:`here` diff --git a/_sources/publishedExamples/runBatteryP2D_source.rst.txt b/_sources/publishedExamples/runBatteryP2D_source.rst.txt index 7a7f9bb8..acb90689 100644 --- a/_sources/publishedExamples/runBatteryP2D_source.rst.txt +++ b/_sources/publishedExamples/runBatteryP2D_source.rst.txt @@ -28,7 +28,7 @@ Source code for runBatteryP2D % used to initialize the simulation and it propagates all the parameters % throughout the submodels. The input parameters can be set manually or % provided in json format. All the parameters for the model are stored in - % the paramobj object. + % the inputparams object. jsonstruct = parseBattmoJson(fullfile('ParameterData','BatteryCellParameters','LithiumIonBatteryCell','lithium_ion_battery_nmc_graphite.json')); @@ -47,19 +47,22 @@ Source code for runBatteryP2D jsonstruct.use_thermal = false; jsonstruct.include_current_collectors = false; - paramobj = BatteryInputParams(jsonstruct); + inputparams = BatteryInputParams(jsonstruct); - use_cccv = false; + use_cccv = true; if use_cccv - cccvstruct = struct( 'controlPolicy' , 'CCCV', ... - 'initialControl' , 'discharging', ... - 'CRate' , 1 , ... - 'lowerCutoffVoltage', 2.4 , ... - 'upperCutoffVoltage', 4.1 , ... - 'dIdtLimit' , 0.01 , ... - 'dEdtLimit' , 0.01); - cccvparamobj = CcCvControlModelInputParams(cccvstruct); - paramobj.Control = cccvparamobj; + inputparams.SOC = 0; + cccvstruct = struct( 'controlPolicy' , 'CCCV' , ... + 'initialControl' , 'charging', ... + 'numberOfCycles' , 2 , ... + 'CRate' , 1.5 , ... + 'DRate' , 1 , ... + 'lowerCutoffVoltage', 3 , ... + 'upperCutoffVoltage', 4 , ... + 'dIdtLimit' , 1e-2 , ... + 'dEdtLimit' , 1e-4); + cccvinputparams = CcCvControlModelInputParams(cccvstruct); + inputparams.Control = cccvinputparams; end @@ -69,16 +72,14 @@ Source code for runBatteryP2D % in the class BatteryGeneratorP2D. gen = BatteryGeneratorP2D(); - % Now, we update the paramobj with the properties of the grid. - paramobj = gen.updateBatteryInputParams(paramobj); + % Now, we update the inputparams with the properties of the grid. + inputparams = gen.updateBatteryInputParams(inputparams); %% Initialize the battery model. - % The battery model is initialized by sending paramobj to the Battery class + % The battery model is initialized by sending inputparams to the Battery class % constructor. see :class:`Battery `. - model = Battery(paramobj); - - model.AutoDiffBackend= AutoDiffBackend(); + model = GenericBattery(inputparams); inspectgraph = false; if inspectgraph @@ -86,32 +87,13 @@ Source code for runBatteryP2D return end - %% Compute the nominal cell capacity and choose a C-Rate - % The nominal capacity of the cell is calculated from the active materials. - % This value is then combined with the user-defined C-Rate to set the cell - % operational current. - - CRate = model.Control.CRate; - - %% Setup the time step schedule - % Smaller time steps are used to ramp up the current from zero to its - % operational value. Larger time steps are then used for the normal - % operation. - switch model.(ctrl).controlPolicy - case 'CCCV' - total = 3.5*hour/CRate; - case 'CCDischarge' - total = 1.4*hour/CRate; - otherwise - error('control policy not recognized'); - end - n = 100; - dt = total/n; - step = struct('val', dt*ones(n, 1), 'control', ones(n, 1)); + %% Setup the schedule + % - % we setup the control by assigning a source and stop function. + timestep.timeStepDuration = 100; + step = model.Control.setupScheduleStep(timestep); control = model.Control.setupScheduleControl(); % This control is used to set up the schedule @@ -150,9 +132,16 @@ Source code for runBatteryP2D nls.maxIterations = 10; % Change default behavior of nonlinear solver, in case of error nls.errorOnFailure = false; - nls.timeStepSelector = StateChangeTimeStepSelector('TargetProps', {{'Control','E'}}, 'targetChangeAbs', 0.03); + % nls.timeStepSelector = StateChangeTimeStepSelector('TargetProps', {{'Control','E'}}, 'targetChangeAbs', 0.03); % Change default tolerance for nonlinear solver - model.nonlinearTolerance = 1e-3*model.Control.Imax; + nls.maxTimestepCuts = 6; + + if use_cccv + Imax = (model.(ctrl).ImaxDischarge + model.(ctrl).ImaxCharge); + else + Imax = model.(ctrl).Imax; + end + model.nonlinearTolerance = 1e-6*Imax; % Set verbosity model.verbose = true; @@ -170,11 +159,17 @@ Source code for runBatteryP2D time = cellfun(@(x) x.time, states); figure - plot(time/hour, E); + plot(time/hour, E, '*-'); grid on xlabel 'time / h'; ylabel 'potential / V'; + figure + plot(time/hour, I, '*-'); + grid on + xlabel 'time / h'; + ylabel 'Current / A'; + writeh5 = false; if writeh5 writeOutput(model, states, 'output.h5'); @@ -182,7 +177,7 @@ Source code for runBatteryP2D %{ - Copyright 2021-2023 SINTEF Industry, Sustainable Energy Technology + Copyright 2021-2024 SINTEF Industry, Sustainable Energy Technology and SINTEF Digital, Mathematics & Cybernetics. This file is part of The Battery Modeling Toolbox BattMo diff --git a/_sources/publishedExamples/runElectrolyser.rst.txt b/_sources/publishedExamples/runElectrolyser.rst.txt index c8015f8a..21bb42c4 100644 --- a/_sources/publishedExamples/runElectrolyser.rst.txt +++ b/_sources/publishedExamples/runElectrolyser.rst.txt @@ -148,55 +148,57 @@ We consider the three domains and plot the pH in each of those. We setup the hel .. code-block:: matlab - models = {model.(oer).(ptl), ... - model.(her).(ptl), ... - model.(inm)}; + doplot = false; - fields = {{'OxygenEvolutionElectrode', 'PorousTransportLayer', 'concentrations', 2} , ... - {'HydrogenEvolutionElectrode', 'PorousTransportLayer', 'concentrations', 2}, ... - {'IonomerMembrane', 'cOH'}}; + if doplot - h = figure(); - set(h, 'position', [10, 10, 800, 450]); - hold on + models = {model.(oer).(ptl), ... + model.(her).(ptl), ... + model.(inm)}; - ntime = numel(time); - times = linspace(1, ntime, 10); - cmap = cmocean('deep', 10); + fields = {{'OxygenEvolutionElectrode', 'PorousTransportLayer', 'concentrations', 2} , ... + {'HydrogenEvolutionElectrode', 'PorousTransportLayer', 'concentrations', 2}, ... + {'IonomerMembrane', 'cOH'}}; - for ifield = 1 : numel(fields) + h = figure(); + set(h, 'position', [10, 10, 800, 450]); + hold on - fd = fields{ifield}; - submodel = models{ifield}; + ntime = numel(time); + times = linspace(1, ntime, 10); + cmap = cmocean('deep', 10); - x = submodel.grid.cells.centroids; + for ifield = 1 : numel(fields) - for itimes = 1 : numel(times); + fd = fields{ifield}; + submodel = models{ifield}; - itime = floor(times(itimes)); - % The method :code:`getProp` is used to recover the value from the state structure - val = model.getProp(states{itime}, fd); - pH = 14 + log10(val/(mol/litre)); + x = submodel.G.cells.centroids; - % plot of pH for the current submodel. - plot(x/(milli*meter), pH, 'color', cmap(itimes, :)); + for itimes = 1 : numel(times); - end + itime = floor(times(itimes)); + % The method :code:`getProp` is used to recover the value from the state structure + val = model.getProp(states{itime}, fd); + pH = 14 + log10(val/(mol/litre)); - end + % plot of pH for the current submodel. + plot(x/(milli*meter), pH, 'color', cmap(itimes, :)); - xlabel('x / mm'); - ylabel('pH'); - title('pH distribution in electrolyser') + end - colormap(cmap) - hColorbar = colorbar; - caxis([0 3]); - hTitle = get(hColorbar, 'Title'); - set(hTitle, 'string', 'J (A/cm^2)'); - -.. figure:: runElectrolyser_02.png - :figwidth: 100% + end + + xlabel('x / mm'); + ylabel('pH'); + title('pH distribition in electrolyser') + + colormap(cmap) + hColorbar = colorbar; + caxis([0 3]); + hTitle = get(hColorbar, 'Title'); + set(hTitle, 'string', 'J (A/cm^2)'); + end diff --git a/_sources/publishedExamples/runElectrolyser_source.rst.txt b/_sources/publishedExamples/runElectrolyser_source.rst.txt index 1f703836..bc2c5191 100644 --- a/_sources/publishedExamples/runElectrolyser_source.rst.txt +++ b/_sources/publishedExamples/runElectrolyser_source.rst.txt @@ -115,52 +115,57 @@ Source code for runElectrolyser % We consider the three domains and plot the pH in each of those. We setup the helper structures to iterate over each % domain for the plot. - models = {model.(oer).(ptl), ... - model.(her).(ptl), ... - model.(inm)}; + doplot = false; - fields = {{'OxygenEvolutionElectrode', 'PorousTransportLayer', 'concentrations', 2} , ... - {'HydrogenEvolutionElectrode', 'PorousTransportLayer', 'concentrations', 2}, ... - {'IonomerMembrane', 'cOH'}}; + if doplot - h = figure(); - set(h, 'position', [10, 10, 800, 450]); - hold on + models = {model.(oer).(ptl), ... + model.(her).(ptl), ... + model.(inm)}; - ntime = numel(time); - times = linspace(1, ntime, 10); - cmap = cmocean('deep', 10); + fields = {{'OxygenEvolutionElectrode', 'PorousTransportLayer', 'concentrations', 2} , ... + {'HydrogenEvolutionElectrode', 'PorousTransportLayer', 'concentrations', 2}, ... + {'IonomerMembrane', 'cOH'}}; - for ifield = 1 : numel(fields) + h = figure(); + set(h, 'position', [10, 10, 800, 450]); + hold on - fd = fields{ifield}; - submodel = models{ifield}; + ntime = numel(time); + times = linspace(1, ntime, 10); + cmap = cmocean('deep', 10); - x = submodel.grid.cells.centroids; + for ifield = 1 : numel(fields) - for itimes = 1 : numel(times); + fd = fields{ifield}; + submodel = models{ifield}; - itime = floor(times(itimes)); - % The method :code:`getProp` is used to recover the value from the state structure - val = model.getProp(states{itime}, fd); - pH = 14 + log10(val/(mol/litre)); + x = submodel.G.cells.centroids; - % plot of pH for the current submodel. - plot(x/(milli*meter), pH, 'color', cmap(itimes, :)); + for itimes = 1 : numel(times); - end + itime = floor(times(itimes)); + % The method :code:`getProp` is used to recover the value from the state structure + val = model.getProp(states{itime}, fd); + pH = 14 + log10(val/(mol/litre)); - end + % plot of pH for the current submodel. + plot(x/(milli*meter), pH, 'color', cmap(itimes, :)); + + end - xlabel('x / mm'); - ylabel('pH'); - title('pH distribution in electrolyser') + end + + xlabel('x / mm'); + ylabel('pH'); + title('pH distribition in electrolyser') - colormap(cmap) - hColorbar = colorbar; - caxis([0 3]); - hTitle = get(hColorbar, 'Title'); - set(hTitle, 'string', 'J (A/cm^2)'); + colormap(cmap) + hColorbar = colorbar; + caxis([0 3]); + hTitle = get(hColorbar, 'Title'); + set(hTitle, 'string', 'J (A/cm^2)'); + end %{ Copyright 2021-2024 SINTEF Industry, Sustainable Energy Technology diff --git a/_sources/publishedExamples/runJsonScript.rst.txt b/_sources/publishedExamples/runJsonScript.rst.txt index 2a5f031b..c3395aa5 100644 --- a/_sources/publishedExamples/runJsonScript.rst.txt +++ b/_sources/publishedExamples/runJsonScript.rst.txt @@ -49,7 +49,7 @@ We load the json structure for the geometrical properties .. code-block:: matlab - jsonfilename = fullfile('Examples', 'jsondatafiles', 'cc_discharge_control.json'); + jsonfilename = fullfile('Examples', 'jsondatafiles', 'ie_control.json'); jsonstruct_control = parseBattmoJson(jsonfilename); @@ -89,7 +89,7 @@ We adjust the total time with respect to the given CRate. CRate = jsonstruct.Control.CRate; jsonstruct.TimeStepping.totalTime = 1.4*hour/CRate; - jsonstruct.TimeStepping.numberOfTimeSteps = 40; + jsonstruct.TimeStepping.N = 40; We start the simulation diff --git a/_sources/publishedExamples/runJsonScript_source.rst.txt b/_sources/publishedExamples/runJsonScript_source.rst.txt index a914ffb6..9092a56c 100644 --- a/_sources/publishedExamples/runJsonScript_source.rst.txt +++ b/_sources/publishedExamples/runJsonScript_source.rst.txt @@ -36,7 +36,7 @@ Source code for runJsonScript %% Control % We load the json structure for the geometrical properties - jsonfilename = fullfile('Examples', 'jsondatafiles', 'cc_discharge_control.json'); + jsonfilename = fullfile('Examples', 'jsondatafiles', 'ie_control.json'); jsonstruct_control = parseBattmoJson(jsonfilename); %% Simulation parameters @@ -65,7 +65,7 @@ Source code for runJsonScript CRate = jsonstruct.Control.CRate; jsonstruct.TimeStepping.totalTime = 1.4*hour/CRate; - jsonstruct.TimeStepping.numberOfTimeSteps = 40; + jsonstruct.TimeStepping.N = 40; %% We start the simulation % We use the function :code:`runBatteryJson` to run the simulation with json input structure diff --git a/_sources/publishedExamples/runProtonicCell.rst.txt b/_sources/publishedExamples/runProtonicCell.rst.txt new file mode 100644 index 00000000..249bb3de --- /dev/null +++ b/_sources/publishedExamples/runProtonicCell.rst.txt @@ -0,0 +1,391 @@ +.. _runProtonicCell: + + +================================ +PEM electrolyser with Gas Supply +================================ +*Generated from runProtonicCell.m* + + + +json input data +=============== +We load the input data that is given by json structures. The physical properties of the supply gas layer is given in the json file :battmofile:`gas-supply-whole-cell.json ` + +.. code-block:: matlab + + clear jsonstruct_material + filename = 'ProtonicMembrane/jsonfiles/gas-supply-whole-cell.json'; + jsonstruct_material.GasSupply = parseBattmoJson(filename); + filename = 'ProtonicMembrane/jsonfiles/protonicMembrane.json'; + jsonstruct_material.Electrolyser = parseBattmoJson(filename); + + jsonstruct_material = removeJsonStructFields(jsonstruct_material, ... + {'Electrolyser', 'Electrolyte', 'Nx'}, ... + {'Electrolyser', 'Electrolyte', 'xlength'}); + +The geometrical property of the cell is given in :battmofile:`2d-cell-geometry.json ` + +.. code-block:: matlab + + filename = 'ProtonicMembrane/jsonfiles/2d-cell-geometry.json'; + jsonstruct_geometry = parseBattmoJson(filename); + +The initial state is given in :battmofile:`gas-supply-initialization.json ` + +.. code-block:: matlab + + filename = 'ProtonicMembrane/jsonfiles/gas-supply-initialization.json'; + jsonstruct_initialization.GasSupply = parseBattmoJson(filename); + +The time stepping parameters are given in :battmofile:`cell-timestepping.json ` + +.. code-block:: matlab + + filename = 'ProtonicMembrane/jsonfiles/cell-timestepping.json'; + jsonstruct_timestepping = parseBattmoJson(filename); + +We merge all the json struct we have created to obtain a complete json structure that can be use to setup the model + +.. code-block:: matlab + + jsonstruct = mergeJsonStructs({jsonstruct_material , ... + jsonstruct_geometry , ... + jsonstruct_initialization, ... + jsonstruct_timestepping}); + +We change the value of the current density to the value we want to use in this simulation + +.. code-block:: matlab + + jsonstruct.Electrolyser.Control.currentDensity = 0.1*ampere/((centi*meter)^2); + + +Input parameter setup +===================== +We setup the input parameter structure which will we be used to instantiate the model + +.. code-block:: matlab + + inputparams = ProtonicMembraneCellInputParams(jsonstruct); + +We setup the grid, by calling the function :battmo:`setupProtonicMembraneGasLayerGrid` + +.. code-block:: matlab + + [inputparams, gen] = setupProtonicMembraneCellGrid(inputparams, jsonstruct); + + +Model setup +=========== +We setup the model for the full cell (electrolyser and a gas supply layer). + +.. code-block:: matlab + + model = ProtonicMembraneCell(inputparams); + +The model is equipped for simulation using the following command (this step may become unnecessary in future versions) + +.. code-block:: matlab + + model = model.setupForSimulation(); + + +Grid plots +========== +We plot the different regions with their grids. +To resolve the non-linearity in the electrolyte, we need a very fine mesh. Plotting the full mesh including the edges for this domain will hide its structure. Therefore we set the option :code:`edgecolor` to :code:`none`. + +.. code-block:: matlab + + figure('position', [337, 757, 3068, 557]) + hold on + plotGrid(model.grid, 'edgecolor', 'none') + plotGrid(model.Electrolyser.grid, 'facecolor', 'red', 'edgecolor', 'none') + plotGrid(model.GasSupply.grid, 'facecolor', 0.9*[0 1 1], 'edgealpha', 0.2) + +.. figure:: runProtonicCell_01.png + :figwidth: 100% + +We plot the boundary and interface faces + +.. code-block:: matlab + + s = spring(10); + opts = {'linewidth', 10, ... + 'edgecolor', s(8, :)}; + +we plot the inlet faces + +.. code-block:: matlab + + figure('position', [337, 757, 3068, 557]) + plotGrid(model.Electrolyser.grid, 'facecolor', 'red', 'edgecolor', 'none') + plotGrid(model.GasSupply.grid, 'facecolor', 'none', 'edgealpha', 0.2) + plotFaces(model.GasSupply.grid, model.GasSupply.couplingTerms{1}.couplingfaces, opts{:}); + +.. figure:: runProtonicCell_02.png + :figwidth: 100% + +we add the outlet faces + +.. code-block:: matlab + + plotFaces(model.GasSupply.grid, model.GasSupply.couplingTerms{2}.couplingfaces, opts{:}); + +.. figure:: runProtonicCell_03.png + :figwidth: 100% + +we add the interface faces + +.. code-block:: matlab + + plotFaces(model.GasSupply.grid, model.couplingTerm.couplingfaces(:, 1) , opts{:}); + +.. figure:: runProtonicCell_04.png + :figwidth: 100% + + +Setup initial state +=================== +The initial state for the cell is used using the initial state of the gas layer that have been loaded (see :battmofile:`here `) + +.. code-block:: matlab + + initstate = model.setupInitialState(jsonstruct); + + +Setup schedule +============== +We setup the time stepping. We are computing the steady state solution, using the the time evolution equation. Note that we also use a numerical method which gradually introduces the high nonlinearities inherent to the problem (in particular the exponential dependence of the electronic conductivity in the membrane). Therefore, the intermediate solutions (i.e. those computed before the final step) should be considered with care. + +.. code-block:: matlab + + schedule = model.setupSchedule(jsonstruct); + + +Setup nonlinear solver +====================== +We use an adaptive time stepping. In this case, the solver will try to keep the number of timesteps equal to 5, based on the timestepping history. + +.. code-block:: matlab + + ts = IterationCountTimeStepSelector('targetIterationCount', 5); + + nls = NonLinearSolver(); + nls.timeStepSelector = ts; + nls.maxIterations = 15; + + +Start simulation +================ +We start the simulation + +.. code-block:: matlab + + [~, states, report] = simulateScheduleAD(initstate, model, schedule, 'OutputMinisteps', true, 'NonLinearSolver', nls); + + +plotting setup +============== + +.. code-block:: matlab + + close all + + set(0, 'defaultlinelinewidth', 3); + set(0, 'defaultaxesfontsize', 15); + set(0, 'defaultfigureposition', [1290, 755, 1275, 559]) + + elyser = 'Electrolyser'; + elyte = 'Electrolyte'; + gs = 'GasSupply'; + + state = states{end}; + state = model.addVariables(state); + + +Electrolyte results +=================== +We plot the electrostatic potential :math:`\phi` (we need to remove the plotting of the grid edges, otherwise due to the grid refinement, they will hide completely the color of the field) + +.. code-block:: matlab + + figure + plotCellData(model.(elyser).(elyte).grid, state.(elyser).(elyte).phi, 'edgecolor', 'none'); + title('Electrostatic Potential \phi / V') + colorbar + +.. figure:: runProtonicCell_05.png + :figwidth: 100% + +We want also to plot the result as a surface plot. Then, we need to manipulate the output and make it suitable to the :code:`surf` function of matlab (we do not explain those details here) + +.. code-block:: matlab + + N = gen.nxElectrolyser; + xc = model.(elyser).(elyte).grid.cells.centroids(1 : N, 1); + + X = reshape(model.(elyser).(elyte).grid.cells.centroids(:, 1), N, [])/(milli*meter); + Y = reshape(model.(elyser).(elyte).grid.cells.centroids(:, 2), N, [])/(milli*meter); + + figure + val = state.(elyser).(elyte).phi; + Z = reshape(val, N, []); + surf(X, Y, Z, 'edgecolor', 'none'); + title('\phi / V') + xlabel('x / mm') + ylabel('y / mm') + view(45, 31) + colorbar + +.. figure:: runProtonicCell_06.png + :figwidth: 100% + +We produce a surface plot of the electromotive potential :math:`\pi`. + +.. code-block:: matlab + + figure + val = state.(elyser).(elyte).pi; + Z = reshape(val, N, []); + surf(X, Y, Z, 'edgecolor', 'none'); + title('pi / V') + xlabel('x / mm') + ylabel('y / mm') + view(45, 31) + colorbar + +.. figure:: runProtonicCell_07.png + :figwidth: 100% + + +Gas Layer results +================= +We plot the H2O mass fraction in the gas diffusion layer. We observe how the water is being first consumed close to the inlet (inlet is at bottom, outlet at top). + +.. code-block:: matlab + + figure + plotCellData(model.(gs).grid, state.(gs).massfractions{1}, 'edgecolor', 'none'); + title('H2O mass fraction / -') + colorbar + +.. figure:: runProtonicCell_08.png + :figwidth: 100% + +We plot the same result as a surface plot + +.. code-block:: matlab + + N = gen.nxGasSupply; + + X = reshape(model.(gs).grid.cells.centroids(:, 1), N, [])/(milli*meter); + Y = reshape(model.(gs).grid.cells.centroids(:, 2), N, [])/(milli*meter); + + + val = state.(gs).massfractions{1}; + Z = reshape(val, N, []); + + surf(X, Y, Z, 'edgecolor', 'none'); + colorbar + title('Mass Fraction H2O'); + xlabel('x / mm') + ylabel('y / mm') + view([50, 51]); + +.. figure:: runProtonicCell_09.png + :figwidth: 100% + +We plot the O2 mass fraction + +.. code-block:: matlab + + figure('position', [1290, 755, 1275, 559]) + + val = state.(gs).massfractions{2}; + Z = reshape(val, N, []); + + surf(X, Y, Z, 'edgecolor', 'none'); + colorbar + title('Mass Fraction O2'); + xlabel('x / mm') + ylabel('y / mm') + view([50, 51]); + +.. figure:: runProtonicCell_10.png + :figwidth: 100% + + +Interface results +================= +Current density in the anode. We recover the current on each face along the anode. + +.. code-block:: matlab + + i = state.Electrolyser.Anode.i; + +From the current values at each face, we compute the current density by dividing with the face areas. + +.. code-block:: matlab + + ind = model.Electrolyser.couplingTerms{1}.couplingfaces(:, 2); + yc = model.Electrolyser.Electrolyte.grid.faces.centroids(ind, 2); + areas = model.Electrolyser.Electrolyte.grid.faces.areas(ind); + + u = ampere/((centi*meter)^2); + i = (i./areas)/u; % We convert to A/cm^2 + + figure + plot(yc/(milli*meter), i); + title('Current in Anode / A/cm^2') + xlabel('height / mm') + +.. figure:: runProtonicCell_11.png + :figwidth: 100% + +We do the same but now for the proton current. + +.. code-block:: matlab + + iHp = state.Electrolyser.Anode.iHp; + + ind = model.Electrolyser.couplingTerms{1}.couplingfaces(:, 2); + yc = model.Electrolyser.Electrolyte.grid.faces.centroids(ind, 2); + areas = model.Electrolyser.Electrolyte.grid.faces.areas(ind); + + u = ampere/((centi*meter)^2); + iHp = (iHp./areas)/u; + + figure + plot(yc/(milli*meter), iHp); + title('iHp in Anode / A/cm^2') + xlabel('height / mm') + +.. figure:: runProtonicCell_12.png + :figwidth: 100% + +By dividing the proton current density with the total current density, we obtain the Faradic efficiency. + +.. code-block:: matlab + + % drivingForces.src = schedule.control.src; + % state = model.evalVarName(state, 'Electrolyser.Anode.iHp', {{'drivingForces', drivingForces}}); + + i = state.Electrolyser.Anode.i; + iHp = state.Electrolyser.Anode.iHp; + + ind = model.Electrolyser.couplingTerms{1}.couplingfaces(:, 2); + yc = model.Electrolyser.Electrolyte.grid.faces.centroids(ind, 2); + + figure + plot(yc/(milli*meter), iHp./i); + title('Faradic efficiency') + xlabel('height / mm') + +.. figure:: runProtonicCell_13.png + :figwidth: 100% + + + +complete source code can be found :ref:`here` diff --git a/_sources/publishedExamples/runProtonicCell_source.rst.txt b/_sources/publishedExamples/runProtonicCell_source.rst.txt new file mode 100644 index 00000000..510a6b4c --- /dev/null +++ b/_sources/publishedExamples/runProtonicCell_source.rst.txt @@ -0,0 +1,321 @@ +:orphan: + +.. _runProtonicCell_source: + +Source code for runProtonicCell +------------------------------- + +.. code:: matlab + + + %% PEM electrolyser with Gas Supply + % + + %% json input data + % + % We load the input data that is given by json structures. The physical properties of the supply gas layer is given in + % the json file :battmofile:`gas-supply-whole-cell.json ` + + clear jsonstruct_material + filename = 'ProtonicMembrane/jsonfiles/gas-supply-whole-cell.json'; + jsonstruct_material.GasSupply = parseBattmoJson(filename); + filename = 'ProtonicMembrane/jsonfiles/protonicMembrane.json'; + jsonstruct_material.Electrolyser = parseBattmoJson(filename); + + jsonstruct_material = removeJsonStructFields(jsonstruct_material, ... + {'Electrolyser', 'Electrolyte', 'Nx'}, ... + {'Electrolyser', 'Electrolyte', 'xlength'}); + + %% + % The geometrical property of the cell is given in :battmofile:`2d-cell-geometry.json ` + % + + filename = 'ProtonicMembrane/jsonfiles/2d-cell-geometry.json'; + jsonstruct_geometry = parseBattmoJson(filename); + + %% + % The initial state is given in :battmofile:`gas-supply-initialization.json ` + % + + filename = 'ProtonicMembrane/jsonfiles/gas-supply-initialization.json'; + jsonstruct_initialization.GasSupply = parseBattmoJson(filename); + + %% + % The time stepping parameters are given in :battmofile:`cell-timestepping.json ` + % + + filename = 'ProtonicMembrane/jsonfiles/cell-timestepping.json'; + jsonstruct_timestepping = parseBattmoJson(filename); + + %% + % We merge all the json struct we have created to obtain a complete json structure that can be use to setup the model + % + jsonstruct = mergeJsonStructs({jsonstruct_material , ... + jsonstruct_geometry , ... + jsonstruct_initialization, ... + jsonstruct_timestepping}); + + %% + % We change the value of the current density to the value we want to use in this simulation + + jsonstruct.Electrolyser.Control.currentDensity = 0.1*ampere/((centi*meter)^2); + + %% Input parameter setup + % + % We setup the input parameter structure which will we be used to instantiate the model + % + + inputparams = ProtonicMembraneCellInputParams(jsonstruct); + + %% + % + % We setup the grid, by calling the function :battmo:`setupProtonicMembraneGasLayerGrid` + % + + [inputparams, gen] = setupProtonicMembraneCellGrid(inputparams, jsonstruct); + + %% Model setup + % + % We setup the model for the full cell (electrolyser and a gas supply layer). + + model = ProtonicMembraneCell(inputparams); + + %% + % The model is equipped for simulation using the following command (this step may become unnecessary in future versions) + % + + model = model.setupForSimulation(); + + %% Grid plots + % + % We plot the different regions with their grids. + + %% + % To resolve the non-linearity in the electrolyte, we need a very fine mesh. Plotting the full mesh including the edges + % for this domain will hide its structure. Therefore we set the option :code:`edgecolor` to :code:`none`. + % + figure('position', [337, 757, 3068, 557]) + hold on + plotGrid(model.grid, 'edgecolor', 'none') + plotGrid(model.Electrolyser.grid, 'facecolor', 'red', 'edgecolor', 'none') + plotGrid(model.GasSupply.grid, 'facecolor', 0.9*[0 1 1], 'edgealpha', 0.2) + %% + % We plot the boundary and interface faces + s = spring(10); + opts = {'linewidth', 10, ... + 'edgecolor', s(8, :)}; + %% + % we plot the inlet faces + figure('position', [337, 757, 3068, 557]) + plotGrid(model.Electrolyser.grid, 'facecolor', 'red', 'edgecolor', 'none') + plotGrid(model.GasSupply.grid, 'facecolor', 'none', 'edgealpha', 0.2) + plotFaces(model.GasSupply.grid, model.GasSupply.couplingTerms{1}.couplingfaces, opts{:}); + %% + % we add the outlet faces + plotFaces(model.GasSupply.grid, model.GasSupply.couplingTerms{2}.couplingfaces, opts{:}); + %% + % we add the interface faces + plotFaces(model.GasSupply.grid, model.couplingTerm.couplingfaces(:, 1) , opts{:}); + + %% Setup initial state + % + % The initial state for the cell is used using the initial state of the gas layer that have been loaded (see + % :battmofile:`here `) + initstate = model.setupInitialState(jsonstruct); + + %% Setup schedule + % + % We setup the time stepping. We are computing the steady state solution, using the the time evolution equation. Note + % that we also use a numerical method which gradually introduces the high nonlinearities inherent to the problem (in + % particular the exponential dependence of the electronic conductivity in the membrane). Therefore, the intermediate + % solutions (i.e. those computed before the final step) should be considered with care. + + schedule = model.setupSchedule(jsonstruct); + + %% Setup nonlinear solver + % + % We use an adaptive time stepping. In this case, the solver will try to keep the number of timesteps equal to 5, based + % on the timestepping history. + + ts = IterationCountTimeStepSelector('targetIterationCount', 5); + + nls = NonLinearSolver(); + nls.timeStepSelector = ts; + nls.maxIterations = 15; + + %% Start simulation + % + % We start the simulation + [~, states, report] = simulateScheduleAD(initstate, model, schedule, 'OutputMinisteps', true, 'NonLinearSolver', nls); + + %% plotting setup + % + % + close all + + set(0, 'defaultlinelinewidth', 3); + set(0, 'defaultaxesfontsize', 15); + set(0, 'defaultfigureposition', [1290, 755, 1275, 559]) + + elyser = 'Electrolyser'; + elyte = 'Electrolyte'; + gs = 'GasSupply'; + + state = states{end}; + state = model.addVariables(state); + + %% Electrolyte results + % We plot the electrostatic potential :math:`\phi` (we need to remove the plotting of the grid edges, otherwise due to + % the grid refinement, they will hide completely the color of the field) + % + + figure + plotCellData(model.(elyser).(elyte).grid, state.(elyser).(elyte).phi, 'edgecolor', 'none'); + title('Electrostatic Potential \phi / V') + colorbar + + %% + % + % We want also to plot the result as a surface plot. Then, we need to manipulate the output and make it suitable to the + % :code:`surf` function of matlab (we do not explain those details here) + + N = gen.nxElectrolyser; + xc = model.(elyser).(elyte).grid.cells.centroids(1 : N, 1); + + X = reshape(model.(elyser).(elyte).grid.cells.centroids(:, 1), N, [])/(milli*meter); + Y = reshape(model.(elyser).(elyte).grid.cells.centroids(:, 2), N, [])/(milli*meter); + + figure + val = state.(elyser).(elyte).phi; + Z = reshape(val, N, []); + surf(X, Y, Z, 'edgecolor', 'none'); + title('\phi / V') + xlabel('x / mm') + ylabel('y / mm') + view(45, 31) + colorbar + + %% + % + % We produce a surface plot of the electromotive potential :math:`\pi`. + + figure + val = state.(elyser).(elyte).pi; + Z = reshape(val, N, []); + surf(X, Y, Z, 'edgecolor', 'none'); + title('pi / V') + xlabel('x / mm') + ylabel('y / mm') + view(45, 31) + colorbar + + %% Gas Layer results + % + % We plot the H2O mass fraction in the gas diffusion layer. We observe how the water is being first consumed close to + % the inlet (inlet is at bottom, outlet at top). + % + + figure + plotCellData(model.(gs).grid, state.(gs).massfractions{1}, 'edgecolor', 'none'); + title('H2O mass fraction / -') + colorbar + + + %% + % We plot the same result as a surface plot + % + N = gen.nxGasSupply; + + X = reshape(model.(gs).grid.cells.centroids(:, 1), N, [])/(milli*meter); + Y = reshape(model.(gs).grid.cells.centroids(:, 2), N, [])/(milli*meter); + + + val = state.(gs).massfractions{1}; + Z = reshape(val, N, []); + + surf(X, Y, Z, 'edgecolor', 'none'); + colorbar + title('Mass Fraction H2O'); + xlabel('x / mm') + ylabel('y / mm') + view([50, 51]); + + %% + % + % We plot the O2 mass fraction + % + + figure('position', [1290, 755, 1275, 559]) + + val = state.(gs).massfractions{2}; + Z = reshape(val, N, []); + + surf(X, Y, Z, 'edgecolor', 'none'); + colorbar + title('Mass Fraction O2'); + xlabel('x / mm') + ylabel('y / mm') + view([50, 51]); + + %% Interface results + % + % Current density in the anode. We recover the current on each face along the anode. + % + + i = state.Electrolyser.Anode.i; + + %% + % + % From the current values at each face, we compute the current density by dividing with the face areas. + + ind = model.Electrolyser.couplingTerms{1}.couplingfaces(:, 2); + yc = model.Electrolyser.Electrolyte.grid.faces.centroids(ind, 2); + areas = model.Electrolyser.Electrolyte.grid.faces.areas(ind); + + u = ampere/((centi*meter)^2); + i = (i./areas)/u; % We convert to A/cm^2 + + figure + plot(yc/(milli*meter), i); + title('Current in Anode / A/cm^2') + xlabel('height / mm') + + + %% + % + % We do the same but now for the proton current. + % + + iHp = state.Electrolyser.Anode.iHp; + + ind = model.Electrolyser.couplingTerms{1}.couplingfaces(:, 2); + yc = model.Electrolyser.Electrolyte.grid.faces.centroids(ind, 2); + areas = model.Electrolyser.Electrolyte.grid.faces.areas(ind); + + u = ampere/((centi*meter)^2); + iHp = (iHp./areas)/u; + + figure + plot(yc/(milli*meter), iHp); + title('iHp in Anode / A/cm^2') + xlabel('height / mm') + + %% + % + % By dividing the proton current density with the total current density, we obtain the Faradic efficiency. + + % drivingForces.src = schedule.control.src; + % state = model.evalVarName(state, 'Electrolyser.Anode.iHp', {{'drivingForces', drivingForces}}); + + i = state.Electrolyser.Anode.i; + iHp = state.Electrolyser.Anode.iHp; + + ind = model.Electrolyser.couplingTerms{1}.couplingfaces(:, 2); + yc = model.Electrolyser.Electrolyte.grid.faces.centroids(ind, 2); + + figure + plot(yc/(milli*meter), iHp./i); + title('Faradic efficiency') + xlabel('height / mm') + + diff --git a/_sources/publishedExamples/runProtonicMembrane.rst.txt b/_sources/publishedExamples/runProtonicMembrane.rst.txt index 14e57fa8..20513ce6 100644 --- a/_sources/publishedExamples/runProtonicMembrane.rst.txt +++ b/_sources/publishedExamples/runProtonicMembrane.rst.txt @@ -30,13 +30,13 @@ We setup the input parameter structure which will we be used to instantiate the .. code-block:: matlab - inputparams = ProtonicMembraneCellInputParams(jsonstruct); + inputparams = ProtonicMembraneInputParams(jsonstruct); -We setup the grid, which is done by calling the function :battmo:`setupProtonicMembraneCellGrid` +We setup the grid, which is done by calling the function :battmo:`setupProtonicMembraneGrid` .. code-block:: matlab - [inputparams, gen] = setupProtonicMembraneCellGrid(inputparams, jsonstruct); + [inputparams, gen] = setupProtonicMembraneGrid(inputparams, jsonstruct); Model setup @@ -45,7 +45,7 @@ We instantiate the model for the protonic membrane cell .. code-block:: matlab - model = ProtonicMembraneCell(inputparams); + model = ProtonicMembrane(inputparams); The model is equipped for simulation using the following command (this step may become unnecessary in future versions) @@ -65,12 +65,12 @@ We setup the initial state using a default setup included in the model Schedule ======== -We setup the schedule, which means the timesteps and also the control we want to use. In this case we use current control and the current equal to zero (see :battmofile:`here`). +We setup the schedule, which means the timesteps and also the control we want to use. In this case we use current control and the current equal to zero (see :battmofile:`here `). We compute the steady-state solution and the time stepping here does not correspond to time values but should be seen as step-wise increase of the effect of the non-linearity (in particular in the expression of the conductivity which includes highly nonlineaer effect with the exponential terms. We do not detail here the method). .. code-block:: matlab - schedule = model.Control.setupSchedule(inputparams.jsonstruct); + schedule = model.Control.setupSchedule(jsonstruct); Simulation diff --git a/_sources/publishedExamples/runProtonicMembrane_source.rst.txt b/_sources/publishedExamples/runProtonicMembrane_source.rst.txt index 6d0da8ce..baa938df 100644 --- a/_sources/publishedExamples/runProtonicMembrane_source.rst.txt +++ b/_sources/publishedExamples/runProtonicMembrane_source.rst.txt @@ -25,15 +25,15 @@ Source code for runProtonicMembrane %% Input structure setup % We setup the input parameter structure which will we be used to instantiate the model - inputparams = ProtonicMembraneCellInputParams(jsonstruct); + inputparams = ProtonicMembraneInputParams(jsonstruct); %% - % We setup the grid, which is done by calling the function :battmo:`setupProtonicMembraneCellGrid` - [inputparams, gen] = setupProtonicMembraneCellGrid(inputparams, jsonstruct); + % We setup the grid, which is done by calling the function :battmo:`setupProtonicMembraneGrid` + [inputparams, gen] = setupProtonicMembraneGrid(inputparams, jsonstruct); %% Model setup % We instantiate the model for the protonic membrane cell - model = ProtonicMembraneCell(inputparams); + model = ProtonicMembrane(inputparams); %% % The model is equipped for simulation using the following command (this step may become unnecessary in future versions) @@ -45,13 +45,13 @@ Source code for runProtonicMembrane %% Schedule % We setup the schedule, which means the timesteps and also the control we want to use. In this case we use current - % control and the current equal to zero (see :battmofile:`here`). + % control and the current equal to zero (see :battmofile:`here `). % % We compute the steady-state solution and the time stepping here does not correspond to time values but should be seen % as step-wise increase of the effect of the non-linearity (in particular in the expression of the conductivity which % includes highly nonlineaer effect with the exponential terms. We do not detail here the method). - schedule = model.Control.setupSchedule(inputparams.jsonstruct); + schedule = model.Control.setupSchedule(jsonstruct); %% Simulation % We run the simulation diff --git a/_sources/publishedExamples/runSEIActiveMaterial.rst.txt b/_sources/publishedExamples/runSEIActiveMaterial.rst.txt index 934d82c6..00c6e33c 100644 --- a/_sources/publishedExamples/runSEIActiveMaterial.rst.txt +++ b/_sources/publishedExamples/runSEIActiveMaterial.rst.txt @@ -11,7 +11,7 @@ Particle simulation with SEI layer growth .. code-block:: matlab % clear the workspace and close open figures - clear + clear all close all @@ -55,6 +55,8 @@ Setup the model % We use a stand alone model for the particle paramobj.standAlone = true; + paramobj = paramobj.validateInputParams(); + % We initiate the model model = SEIActiveMaterial(paramobj); @@ -152,7 +154,7 @@ Run simulation .. code-block:: matlab model.verbose = true; - [~, states, report] = simulateScheduleAD(initState, model, schedule, 'OutputMinisteps', true, 'NonLinearSolver', nls); + [wellSols, states, report] = simulateScheduleAD(initState, model, schedule, 'OutputMinisteps', true, 'NonLinearSolver', nls); Plotting diff --git a/_sources/publishedExamples/runSEIActiveMaterial_source.rst.txt b/_sources/publishedExamples/runSEIActiveMaterial_source.rst.txt index a818baae..7062b7d0 100644 --- a/_sources/publishedExamples/runSEIActiveMaterial_source.rst.txt +++ b/_sources/publishedExamples/runSEIActiveMaterial_source.rst.txt @@ -11,7 +11,7 @@ Source code for runSEIActiveMaterial %% Particle simulation with SEI layer growth % clear the workspace and close open figures - clear + clear all close all %% Import the required modules from MRST @@ -41,9 +41,12 @@ Source code for runSEIActiveMaterial % We use a stand alone model for the particle paramobj.standAlone = true; + paramobj = paramobj.validateInputParams(); + % We initiate the model model = SEIActiveMaterial(paramobj); + %% Setup initial state Nsd = model.(sd).N; @@ -56,13 +59,13 @@ Source code for runSEIActiveMaterial % Initial concentration value in the electrolyte cElectrolyte = 5e-1*mol/litre; % Temperature - T = 298.15; + T = 298.15; % The following datas come from :cite:`Safari_2009` % Porosity of the SEI film epsiSEI = 0.05; % Solvent concentration in the bulk of the electrolyte - cECsolution = 4.541*mol/litre; + cECsolution = 4.541*mol/litre; % Solvent concentration in the SEI film cECexternal = epsiSEI*cECsolution; @@ -104,14 +107,14 @@ Source code for runSEIActiveMaterial step = struct('val', dt*ones(n, 1), 'control', ones(n, 1)); % rampup value for the current function, see rampupSwitchControl - tup = dt; + tup = dt; srcfunc = @(time) rampupControl(time, tup, Imax); cmin = (model.(itf).guestStoichiometry0)*(model.(itf).saturationConcentration); control.stopFunction = @(model, state, state0_inner) (state.(sd).cSurface <= cmin); control.src = srcfunc; - schedule = struct('control', control, 'step', step); + schedule = struct('control', control, 'step', step); %% Setup non-linear solver @@ -123,7 +126,7 @@ Source code for runSEIActiveMaterial %% Run simulation model.verbose = true; - [~, states, report] = simulateScheduleAD(initState, model, schedule, 'OutputMinisteps', true, 'NonLinearSolver', nls); + [wellSols, states, report] = simulateScheduleAD(initState, model, schedule, 'OutputMinisteps', true, 'NonLinearSolver', nls); %% Plotting diff --git a/_sources/publishedExamples/runSiliconGraphiteBattery.rst.txt b/_sources/publishedExamples/runSiliconGraphiteBattery.rst.txt index 4653b625..cacbfa3f 100644 --- a/_sources/publishedExamples/runSiliconGraphiteBattery.rst.txt +++ b/_sources/publishedExamples/runSiliconGraphiteBattery.rst.txt @@ -1,14 +1,15 @@ - .. _runSiliconGraphiteBattery: + +==================================== Composite Silicon Graphite electrode --------------------------------------------------------------------- +==================================== *Generated from runSiliconGraphiteBattery.m* Import the required modules from MRST -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +===================================== load MRST modules .. code-block:: matlab @@ -17,7 +18,7 @@ load MRST modules Shortcuts -^^^^^^^^^ +========= We define shorcuts for the sub-models. .. code-block:: matlab @@ -37,12 +38,12 @@ We define shorcuts for the sub-models. Setup the properties of the battery -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +=================================== We load the property of a composite silicon graphite electrode, see :ref:`compositeElectrode` .. code-block:: matlab - jsonstruct_composite_material = parseBattmoJson('ParameterData/BatteryCellParameters/LithiumIonBatteryCell/composite_silicon_graphite.json'); + jsonstruct_composite_material = parseBattmoJson('ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_silicon_graphite.json'); For the remaining properties, we consider a standard data set @@ -74,49 +75,49 @@ We instantiate the battery :code:`InputParams` object .. code-block:: matlab - inputparams = BatteryInputParams(jsonstruct); + paramobj = BatteryInputParams(jsonstruct); We set the mass fractions of the different material in the coating of the negative electrode. This information could have been passed in the json file earlier (:ref:`compositeElectrode`) .. code-block:: matlab - inputparams.(ne).(co).(am1).massFraction = 0.9; - inputparams.(ne).(co).(am2).massFraction = 0.08; - inputparams.(ne).(co).(bd).massFraction = 0.01; - inputparams.(ne).(co).(ad).massFraction = 0.01; + paramobj.(ne).(co).(am1).massFraction = 0.9; + paramobj.(ne).(co).(am2).massFraction = 0.08; + paramobj.(ne).(co).(bd).massFraction = 0.01; + paramobj.(ne).(co).(ad).massFraction = 0.01; We change the given CRate .. code-block:: matlab - inputparams.Control.CRate = 0.1; + paramobj.Control.CRate = 0.1; We validate the :code:`InputParams` using the method :code:`validateInputParams` which belongs to the parent class. This step .. code-block:: matlab - Inputparams = inputparams.validateInputParams(); + Paramobj = paramobj.validateInputParams(); - gen = BatteryGeneratorP2D(); + gen = BatteryGenerator1D(); -Now, we update the inputparams with the properties of the mesh. +Now, we update the paramobj with the properties of the mesh. .. code-block:: matlab - inputparams = gen.updateBatteryInputParams(inputparams); + paramobj = gen.updateBatteryInputParams(paramobj); Model Instantiation -^^^^^^^^^^^^^^^^^^^ +=================== We instantiate the model .. code-block:: matlab - model = Battery(inputparams); + model = Battery(paramobj); Setup schedule (control and time stepping) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +========================================== We will simulate two consecutive periods: a discharge followed by a charge. We start with the charge period @@ -134,13 +135,13 @@ We start with the charge period srcfunc = @(time, I, E) rampupSwitchControl(time, tup, I, E, ... model.Control.Imax, ... model.Control.lowerCutoffVoltage); - control = struct('src', srcfunc, 'CCDischarge', true); + control = struct('src', srcfunc, 'IEswitch', true); schedule = struct('control', control, 'step', step); Setup the initial state of the model -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +==================================== We use the default initialisation given by a method in the model .. code-block:: matlab @@ -149,7 +150,7 @@ We use the default initialisation given by a method in the model Setup the properties of the nonlinear solver -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +============================================ We adjust some settings for the nonlinear solver .. code-block:: matlab @@ -188,7 +189,7 @@ We use verbosity Run the simulation for the discharge -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +==================================== .. code-block:: matlab @@ -198,7 +199,7 @@ Run the simulation for the discharge Setup charge schedule -^^^^^^^^^^^^^^^^^^^^^ +===================== We use the last computed state of the discharge as the initial state for the charge period. .. code-block:: matlab @@ -212,12 +213,12 @@ We use a new control. Note the minus sign in front of :code:`model.Control.Imax` srcfunc = @(time, I, E) rampupSwitchControl(time, tup, I, E, ... -model.Control.Imax, ... model.Control.upperCutoffVoltage); - control = struct('src', srcfunc, 'CCDischarge', true); + control = struct('src', srcfunc, 'IEswitch', true); schedule = struct('control', control, 'step', step); Run the simulation for the charge perios -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +======================================== .. code-block:: matlab @@ -227,7 +228,7 @@ Run the simulation for the charge perios Visualisation -^^^^^^^^^^^^^ +============= We concatenate the states we have computed .. code-block:: matlab diff --git a/_sources/publishedExamples/runSiliconGraphiteBattery_source.rst.txt b/_sources/publishedExamples/runSiliconGraphiteBattery_source.rst.txt index a5000e38..26fc29f1 100644 --- a/_sources/publishedExamples/runSiliconGraphiteBattery_source.rst.txt +++ b/_sources/publishedExamples/runSiliconGraphiteBattery_source.rst.txt @@ -35,7 +35,7 @@ Source code for runSiliconGraphiteBattery % We load the property of a composite silicon graphite electrode, see :ref:`compositeElectrode` % - jsonstruct_composite_material = parseBattmoJson('ParameterData/BatteryCellParameters/LithiumIonBatteryCell/composite_silicon_graphite.json'); + jsonstruct_composite_material = parseBattmoJson('ParameterData/BatteryCellParameters/LithiumIonBatteryCell/lithium_ion_battery_nmc_silicon_graphite.json'); %% % For the remaining properties, we consider a standard data set @@ -58,35 +58,35 @@ Source code for runSiliconGraphiteBattery %% % We instantiate the battery :code:`InputParams` object - inputparams = BatteryInputParams(jsonstruct); + paramobj = BatteryInputParams(jsonstruct); %% % We set the mass fractions of the different material in the coating of the negative electrode. This information could % have been passed in the json file earlier (:ref:`compositeElectrode`) - inputparams.(ne).(co).(am1).massFraction = 0.9; - inputparams.(ne).(co).(am2).massFraction = 0.08; - inputparams.(ne).(co).(bd).massFraction = 0.01; - inputparams.(ne).(co).(ad).massFraction = 0.01; + paramobj.(ne).(co).(am1).massFraction = 0.9; + paramobj.(ne).(co).(am2).massFraction = 0.08; + paramobj.(ne).(co).(bd).massFraction = 0.01; + paramobj.(ne).(co).(ad).massFraction = 0.01; %% % We change the given CRate - inputparams.Control.CRate = 0.1; + paramobj.Control.CRate = 0.1; %% % We validate the :code:`InputParams` using the method :code:`validateInputParams` which belongs to the parent class. This step - Inputparams = inputparams.validateInputParams(); + Paramobj = paramobj.validateInputParams(); - gen = BatteryGeneratorP2D(); + gen = BatteryGenerator1D(); %% - % Now, we update the inputparams with the properties of the mesh. - inputparams = gen.updateBatteryInputParams(inputparams); + % Now, we update the paramobj with the properties of the mesh. + paramobj = gen.updateBatteryInputParams(paramobj); %% Model Instantiation % We instantiate the model - model = Battery(inputparams); + model = Battery(paramobj); %% Setup schedule (control and time stepping) @@ -106,7 +106,7 @@ Source code for runSiliconGraphiteBattery srcfunc = @(time, I, E) rampupSwitchControl(time, tup, I, E, ... model.Control.Imax, ... model.Control.lowerCutoffVoltage); - control = struct('src', srcfunc, 'CCDischarge', true); + control = struct('src', srcfunc, 'IEswitch', true); schedule = struct('control', control, 'step', step); @@ -154,7 +154,7 @@ Source code for runSiliconGraphiteBattery srcfunc = @(time, I, E) rampupSwitchControl(time, tup, I, E, ... -model.Control.Imax, ... model.Control.upperCutoffVoltage); - control = struct('src', srcfunc, 'CCDischarge', true); + control = struct('src', srcfunc, 'IEswitch', true); schedule = struct('control', control, 'step', step); %% Run the simulation for the charge perios diff --git a/advancedtopics.html b/advancedtopics.html index 45f23156..ecf3bd08 100644 --- a/advancedtopics.html +++ b/advancedtopics.html @@ -162,36 +162,54 @@
  • pH distribution plot
  • -
  • Protonic Membrane