diff --git a/pybamm/input/parameters/lithium_ion/Chen2020_composite_halfcell.py b/pybamm/input/parameters/lithium_ion/Chen2020_composite_halfcell.py new file mode 100644 index 0000000000..73d79da8a4 --- /dev/null +++ b/pybamm/input/parameters/lithium_ion/Chen2020_composite_halfcell.py @@ -0,0 +1,377 @@ +import pybamm +import os + + +def graphite_LGM50_electrolyte_exchange_current_density_Chen2020( + c_e, c_s_surf, c_s_max, T +): + """ + Exchange-current density for Butler-Volmer reactions between graphite and LiPF6 in + EC:DMC. + + References + ---------- + .. [1] Chang-Hui Chen, Ferran Brosa Planella, Kieran O’Regan, Dominika Gastol, W. + Dhammika Widanage, and Emma Kendrick. "Development of Experimental Techniques for + Parameterization of Multi-scale Lithium-ion Battery Models." Journal of the + Electrochemical Society 167 (2020): 080534. + + Parameters + ---------- + c_e : :class:`pybamm.Symbol` + Electrolyte concentration [mol.m-3] + c_s_surf : :class:`pybamm.Symbol` + Particle concentration [mol.m-3] + c_s_max : :class:`pybamm.Symbol` + Maximum particle concentration [mol.m-3] + T : :class:`pybamm.Symbol` + Temperature [K] + + Returns + ------- + :class:`pybamm.Symbol` + Exchange-current density [A.m-2] + """ + m_ref = 6.48e-7 # (A/m2)(m3/mol)**1.5 - includes ref concentrations + E_r = 35000 + arrhenius = pybamm.exp(E_r / pybamm.constants.R * (1 / 298.15 - 1 / T)) + + return ( + m_ref * arrhenius * c_e**0.5 * c_s_surf**0.5 * (c_s_max - c_s_surf) ** 0.5 + ) + + +def silicon_ocp_lithiation_Mark2016(sto): + """ + silicon Open-circuit Potential (OCP) as a a function of the + stochiometry. The fit is taken from the Enertech cell [1], which is only accurate + for 0 < sto < 1. + + References + ---------- + .. [1] Verbrugge M, Baker D, Xiao X. Formulation for the treatment of multiple + electrochemical reactions and associated speciation for the Lithium-Silicon + electrode[J]. Journal of The Electrochemical Society, 2015, 163(2): A262. + + Parameters + ---------- + sto: double + Stochiometry of material (li-fraction) + + Returns + ------- + :class:`pybamm.Symbol` + OCP [V] + """ + p1 = -96.63 + p2 = 372.6 + p3 = -587.6 + p4 = 489.9 + p5 = -232.8 + p6 = 62.99 + p7 = -9.286 + p8 = 0.8633 + + U_lithiation = ( + p1 * sto**7 + + p2 * sto**6 + + p3 * sto**5 + + p4 * sto**4 + + p5 * sto**3 + + p6 * sto**2 + + p7 * sto + + p8 + ) + return U_lithiation + + +def silicon_ocp_delithiation_Mark2016(sto): + """ + silicon Open-circuit Potential (OCP) as a a function of the + stochiometry. The fit is taken from the Enertech cell [1], which is only accurate + for 0 < sto < 1. + + References + ---------- + .. [1] Verbrugge M, Baker D, Xiao X. Formulation for the treatment of multiple + electrochemical reactions and associated speciation for the Lithium-Silicon + electrode[J]. Journal of The Electrochemical Society, 2015, 163(2): A262. + + Parameters + ---------- + sto: double + Stochiometry of material (li-fraction) + + Returns + ------- + :class:`pybamm.Symbol` + OCP [V] + """ + p1 = -51.02 + p2 = 161.3 + p3 = -205.7 + p4 = 140.2 + p5 = -58.76 + p6 = 16.87 + p7 = -3.792 + p8 = 0.9937 + + U_delithiation = ( + p1 * sto**7 + + p2 * sto**6 + + p3 * sto**5 + + p4 * sto**4 + + p5 * sto**3 + + p6 * sto**2 + + p7 * sto + + p8 + ) + return U_delithiation + + +def silicon_LGM50_electrolyte_exchange_current_density_Chen2020( + c_e, c_s_surf, c_s_max, T +): + """ + Exchange-current density for Butler-Volmer reactions between silicon and LiPF6 in + EC:DMC. + + References + ---------- + .. [1] Chang-Hui Chen, Ferran Brosa Planella, Kieran O’Regan, Dominika Gastol, W. + Dhammika Widanage, and Emma Kendrick. "Development of Experimental Techniques for + Parameterization of Multi-scale Lithium-ion Battery Models." Journal of the + Electrochemical Society 167 (2020): 080534. + + Parameters + ---------- + c_e : :class:`pybamm.Symbol` + Electrolyte concentration [mol.m-3] + c_s_surf : :class:`pybamm.Symbol` + Particle concentration [mol.m-3] + c_s_max : :class:`pybamm.Symbol` + Maximum particle concentration [mol.m-3] + T : :class:`pybamm.Symbol` + Temperature [K] + + Returns + ------- + :class:`pybamm.Symbol` + Exchange-current density [A.m-2] + """ + + m_ref = ( + 6.48e-7 * 28700 / 278000 + ) # (A/m2)(m3/mol)**1.5 - includes ref concentrations + E_r = 35000 + arrhenius = pybamm.exp(E_r / pybamm.constants.R * (1 / 298.15 - 1 / T)) + + return ( + m_ref * arrhenius * c_e**0.5 * c_s_surf**0.5 * (c_s_max - c_s_surf) ** 0.5 + ) + + +def electrolyte_diffusivity_Nyman2008(c_e, T): + """ + Diffusivity of LiPF6 in EC:EMC (3:7) as a function of ion concentration. The data + comes from [1] + + References + ---------- + .. [1] A. Nyman, M. Behm, and G. Lindbergh, "Electrochemical characterisation and + modelling of the mass transport phenomena in LiPF6-EC-EMC electrolyte," + Electrochim. Acta, vol. 53, no. 22, pp. 6356–6365, 2008. + + Parameters + ---------- + c_e: :class:`pybamm.Symbol` + Dimensional electrolyte concentration + T: :class:`pybamm.Symbol` + Dimensional temperature + + Returns + ------- + :class:`pybamm.Symbol` + Solid diffusivity + """ + + D_c_e = 8.794e-11 * (c_e / 1000) ** 2 - 3.972e-10 * (c_e / 1000) + 4.862e-10 + + # Nyman et al. (2008) does not provide temperature dependence + + return D_c_e + + +def electrolyte_conductivity_Nyman2008(c_e, T): + """ + Conductivity of LiPF6 in EC:EMC (3:7) as a function of ion concentration. The data + comes from [1]. + + References + ---------- + .. [1] A. Nyman, M. Behm, and G. Lindbergh, "Electrochemical characterisation and + modelling of the mass transport phenomena in LiPF6-EC-EMC electrolyte," + Electrochim. Acta, vol. 53, no. 22, pp. 6356–6365, 2008. + + Parameters + ---------- + c_e: :class:`pybamm.Symbol` + Dimensional electrolyte concentration + T: :class:`pybamm.Symbol` + Dimensional temperature + + Returns + ------- + :class:`pybamm.Symbol` + Solid diffusivity + """ + + sigma_e = ( + 0.1297 * (c_e / 1000) ** 3 - 2.51 * (c_e / 1000) ** 1.5 + 3.329 * (c_e / 1000) + ) + + # Nyman et al. (2008) does not provide temperature dependence + + return sigma_e + + +# Load data in the appropriate format +path, _ = os.path.split(os.path.abspath(__file__)) +graphite_ocp_Enertech_Ai2020_data = pybamm.parameters.process_1D_data( + "graphite_ocp_Enertech_Ai2020.csv", path=path +) + + +def graphite_ocp_Enertech_Ai2020(sto): + name, (x, y) = graphite_ocp_Enertech_Ai2020_data + return pybamm.Interpolant(x, y, sto, name=name, interpolator="cubic") + + +# Call dict via a function to avoid errors when editing in place +def get_parameter_values(): + """ + Parameters for a composite graphite/silicon electrode, from the paper + + Weilong Ai, Niall Kirkaldy, Yang Jiang, Gregory Offer, Huizhi Wang, and Billy + Wu. A composite electrode model for lithium-ion batteries with silicon/graphite + negative electrodes. Journal of Power Sources, 527:231142, 2022. URL: + https://www.sciencedirect.com/science/article/pii/S0378775322001604, + doi:https://doi.org/10.1016/j.jpowsour.2022.231142. + + based on the paper + + Chang-Hui Chen, Ferran Brosa Planella, Kieran O'Regan, Dominika Gastol, W. + Dhammika Widanage, and Emma Kendrick. Development of Experimental Techniques for + Parameterization of Multi-scale Lithium-ion Battery Models. Journal of The + Electrochemical Society, 167(8):080534, 2020. doi:10.1149/1945-7111/ab9050. + + and references therein. + + SEI parameters are example parameters for composite SEI on silicon/graphite. Both + phases use the same values, from the paper. + + Xiao Guang Yang, Yongjun Leng, Guangsheng Zhang, Shanhai Ge, and Chao Yang Wang. + Modeling of lithium plating induced aging of lithium-ion batteries: transition + from linear to nonlinear aging. Journal of Power Sources, 360:28–40, 2017. + doi:10.1016/j.jpowsour.2017.05.110. + + """ + + return { + "chemistry": "lithium_ion", + # sei + "Primary: Ratio of lithium moles to SEI moles": 2.0, + "Primary: Inner SEI partial molar volume [m3.mol-1]": 9.585e-05, + "Primary: Outer SEI partial molar volume [m3.mol-1]": 9.585e-05, + "Primary: SEI resistivity [Ohm.m]": 200000.0, + "Primary: Initial inner SEI thickness [m]": 2.5e-09, + "Primary: Initial outer SEI thickness [m]": 2.5e-09, + "Primary: EC initial concentration in electrolyte [mol.m-3]": 4541.0, + "Primary: EC diffusivity [m2.s-1]": 2e-18, + "Primary: SEI kinetic rate constant [m.s-1]": 1e-12, + "Primary: SEI open-circuit potential [V]": 0.4, + "Primary: SEI growth activation energy [J.mol-1]": 0.0, + "Secondary: Ratio of lithium moles to SEI moles": 2.0, + "Secondary: Inner SEI partial molar volume [m3.mol-1]": 9.585e-05, + "Secondary: Outer SEI partial molar volume [m3.mol-1]": 9.585e-05, + "Secondary: SEI resistivity [Ohm.m]": 200000.0, + "Secondary: Initial inner SEI thickness [m]": 2.5e-09, + "Secondary: Initial outer SEI thickness [m]": 2.5e-09, + "Secondary: EC initial concentration in electrolyte [mol.m-3]": 4541.0, + "Secondary: EC diffusivity [m2.s-1]": 2e-18, + "Secondary: SEI kinetic rate constant [m.s-1]": 1e-12, + "Secondary: SEI open-circuit potential [V]": 0.4, + "Secondary: SEI growth activation energy [J.mol-1]": 0.0, + # cell + "Positive current collector thickness [m]": 1.2e-05, + "Positive electrode thickness [m]": 8.52e-05, + "Separator thickness [m]": 1.2e-05, + "Electrode height [m]": 0.065, + "Electrode width [m]": 1.58, + "Cell cooling surface area [m2]": 0.00531, + "Cell volume [m3]": 2.42e-05, + "Cell thermal expansion coefficient [m.K-1]": 1.1e-06, + "Positive current collector conductivity [S.m-1]": 58411000.0, + "Positive current collector density [kg.m-3]": 8960.0, + "Positive current collector specific heat capacity [J.kg-1.K-1]": 385.0, + "Positive current collector thermal conductivity [W.m-1.K-1]": 401.0, + "Nominal cell capacity [A.h]": 5.0, + "Current function [A]": 5.0, + "Contact resistance [Ohm]": 0, + # positive electrode + "Positive electrode conductivity [S.m-1]": 215.0, + "Primary: Maximum concentration in positive electrode [mol.m-3]": 28700.0, + "Primary: Initial concentration in positive electrode [mol.m-3]": 27700.0, + "Primary: Positive electrode diffusivity [m2.s-1]": 5.5e-14, + "Primary: Positive electrode OCP [V]": graphite_ocp_Enertech_Ai2020, + "Negative electrode porosity": 0.25, + "Primary: Positive electrode active material volume fraction": 0.735, + "Primary: Positive particle radius [m]": 5.86e-06, + "Positive electrode Bruggeman coefficient (electrolyte)": 1.5, + "Positive electrode Bruggeman coefficient (electrode)": 0, + "Positive electrode charge transfer coefficient": 0.5, + "Positive electrode double-layer capacity [F.m-2]": 0.2, + "Primary: Positive electrode exchange-current density [A.m-2]" + "": graphite_LGM50_electrolyte_exchange_current_density_Chen2020, + "Primary: Positive electrode density [kg.m-3]": 1657.0, + "Positive electrode specific heat capacity [J.kg-1.K-1]": 700.0, + "Positive electrode thermal conductivity [W.m-1.K-1]": 1.7, + "Primary: Positive electrode OCP entropic change [V.K-1]": 0.0, + "Secondary: Maximum concentration in positive electrode [mol.m-3]": 278000.0, + "Secondary: Initial concentration in positive electrode [mol.m-3]": 276610.0, + "Secondary: Positive electrode diffusivity [m2.s-1]": 1.67e-14, + "Secondary: Positive electrode lithiation OCP [V]" + "": silicon_ocp_lithiation_Mark2016, + "Secondary: Positive electrode delithiation OCP [V]" + "": silicon_ocp_delithiation_Mark2016, + "Secondary: Positive electrode active material volume fraction": 0.015, + "Secondary: Positive particle radius [m]": 1.52e-06, + "Secondary: Positive electrode exchange-current density [A.m-2]" + "": silicon_LGM50_electrolyte_exchange_current_density_Chen2020, + "Secondary: Positive electrode density [kg.m-3]": 2650.0, + "Secondary: Positive electrode OCP entropic change [V.K-1]": 0.0, + # separator + "Separator porosity": 0.47, + "Separator Bruggeman coefficient (electrolyte)": 1.5, + "Separator density [kg.m-3]": 397.0, + "Separator specific heat capacity [J.kg-1.K-1]": 700.0, + "Separator thermal conductivity [W.m-1.K-1]": 0.16, + # electrolyte + "Initial concentration in electrolyte [mol.m-3]": 1000.0, + "Cation transference number": 0.2594, + "Thermodynamic factor": 1.0, + "Electrolyte diffusivity [m2.s-1]": electrolyte_diffusivity_Nyman2008, + "Electrolyte conductivity [S.m-1]": electrolyte_conductivity_Nyman2008, + # experiment + "Reference temperature [K]": 298.15, + "Total heat transfer coefficient [W.m-2.K-1]": 10.0, + "Ambient temperature [K]": 298.15, + "Number of electrodes connected in parallel to make a cell": 1.0, + "Number of cells connected in series to make a battery": 1.0, + "Lower voltage cut-off [V]": 2.5, + "Upper voltage cut-off [V]": 4.2, + "Initial concentration in positive electrode [mol.m-3]": 29866.0, + "Initial temperature [K]": 298.15, + # citations + "citations": ["Chen2020", "Ai2022"], + } diff --git a/pybamm/input/parameters/lithium_ion/Ecker2015_graphite_halfcell.py b/pybamm/input/parameters/lithium_ion/Ecker2015_graphite_halfcell.py new file mode 100644 index 0000000000..d3180ac92b --- /dev/null +++ b/pybamm/input/parameters/lithium_ion/Ecker2015_graphite_halfcell.py @@ -0,0 +1,396 @@ +import pybamm + + +def graphite_diffusivity_Ecker2015(sto, T): + """ + Graphite diffusivity as a function of stochiometry [1, 2, 3]. + + References + ---------- + .. [1] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery i. determination of parameters." Journal of the + Electrochemical Society 162.9 (2015): A1836-A1848. + .. [2] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery ii. model validation." Journal of The Electrochemical + Society 162.9 (2015): A1849-A1857. + .. [3] Richardson, Giles, et. al. "Generalised single particle models for + high-rate operation of graded lithium-ion electrodes: Systematic derivation + and validation." Electrochemica Acta 339 (2020): 135862 + + Parameters + ---------- + sto: :class:`pybamm.Symbol` + Electrode stochiometry + T: :class:`pybamm.Symbol` + Dimensional temperature + + Returns + ------- + :class:`pybamm.Symbol` + Solid diffusivity + """ + + D_ref = 8.4e-13 * pybamm.exp(-11.3 * sto) + 8.2e-15 + E_D_s = 3.03e4 + arrhenius = pybamm.exp(-E_D_s / (pybamm.constants.R * T)) * pybamm.exp( + E_D_s / (pybamm.constants.R * 296) + ) + + return D_ref * arrhenius + + +def graphite_ocp_Ecker2015(sto): + """ + Graphite OCP as a function of stochiometry [1, 2, 3]. + + References + ---------- + .. [1] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery i. determination of parameters." Journal of the + Electrochemical Society 162.9 (2015): A1836-A1848. + .. [2] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery ii. model validation." Journal of The Electrochemical + Society 162.9 (2015): A1849-A1857. + .. [3] Richardson, Giles, et. al. "Generalised single particle models for + high-rate operation of graded lithium-ion electrodes: Systematic derivation + and validation." Electrochemica Acta 339 (2020): 135862 + + Parameters + ---------- + sto: :class:`pybamm.Symbol` + Electrode stochiometry + + Returns + ------- + :class:`pybamm.Symbol` + Open-circuit potential + """ + + # Graphite electrode from Ecker, Kabitz, Laresgoiti et al. + # Analytical fit (WebPlotDigitizer + gnuplot) + a = 0.716502 + b = 369.028 + c = 0.12193 + d = 35.6478 + e = 0.0530947 + g = 0.0169644 + h = 27.1365 + i = 0.312832 + j = 0.0199313 + k = 28.5697 + m = 0.614221 + n = 0.931153 + o = 36.328 + p = 1.10743 + q = 0.140031 + r = 0.0189193 + s = 21.1967 + t = 0.196176 + + u_eq = ( + a * pybamm.exp(-b * sto) + + c * pybamm.exp(-d * (sto - e)) + - r * pybamm.tanh(s * (sto - t)) + - g * pybamm.tanh(h * (sto - i)) + - j * pybamm.tanh(k * (sto - m)) + - n * pybamm.exp(o * (sto - p)) + + q + ) + + return u_eq + + +def graphite_electrolyte_exchange_current_density_Ecker2015(c_e, c_s_surf, c_s_max, T): + """ + Exchange-current density for Butler-Volmer reactions between graphite and LiPF6 in + EC:DMC. + + References + ---------- + .. [1] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery i. determination of parameters." Journal of the + Electrochemical Society 162.9 (2015): A1836-A1848. + .. [2] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery ii. model validation." Journal of The Electrochemical + Society 162.9 (2015): A1849-A1857. + .. [3] Richardson, Giles, et. al. "Generalised single particle models for + high-rate operation of graded lithium-ion electrodes: Systematic derivation + and validation." Electrochemica Acta 339 (2020): 135862 + + Parameters + ---------- + c_e : :class:`pybamm.Symbol` + Electrolyte concentration [mol.m-3] + c_s_surf : :class:`pybamm.Symbol` + Particle concentration [mol.m-3] + c_s_max : :class:`pybamm.Symbol` + Maximum particle concentration [mol.m-3] + T : :class:`pybamm.Symbol` + Temperature [K] + + Returns + ------- + :class:`pybamm.Symbol` + Exchange-current density [A.m-2] + """ + + k_ref = 1.11 * 1e-10 + + # multiply by Faraday's constant to get correct units + m_ref = ( + pybamm.constants.F * k_ref + ) # (A/m2)(m3/mol)**1.5 - includes ref concentrations + E_r = 53400 + + arrhenius = pybamm.exp(-E_r / (pybamm.constants.R * T)) * pybamm.exp( + E_r / (pybamm.constants.R * 296.15) + ) + + return ( + m_ref * arrhenius * c_e**0.5 * c_s_surf**0.5 * (c_s_max - c_s_surf) ** 0.5 + ) + + +def electrolyte_diffusivity_Ecker2015(c_e, T): + """ + Diffusivity of LiPF6 in EC:DMC as a function of ion concentration [1, 2, 3]. + + References + ---------- + .. [1] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery i. determination of parameters." Journal of the + Electrochemical Society 162.9 (2015): A1836-A1848. + .. [2] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery ii. model validation." Journal of The Electrochemical + Society 162.9 (2015): A1849-A1857. + .. [3] Richardson, Giles, et. al. "Generalised single particle models for + high-rate operation of graded lithium-ion electrodes: Systematic derivation + and validation." Electrochemica Acta 339 (2020): 135862 + + Parameters + ---------- + c_e: :class:`pybamm.Symbol` + Dimensional electrolyte concentration + T: :class:`pybamm.Symbol` + Dimensional temperature + + Returns + ------- + :class:`pybamm.Symbol` + Solid diffusivity + """ + + # The diffusivity epends on the electrolyte conductivity + inputs = {"Electrolyte concentration [mol.m-3]": c_e, "Temperature [K]": T} + sigma_e = pybamm.FunctionParameter("Electrolyte conductivity [S.m-1]", inputs) + + D_c_e = ( + (pybamm.constants.k_b / (pybamm.constants.F * pybamm.constants.q_e)) + * sigma_e + * T + / c_e + ) + + return D_c_e + + +def electrolyte_conductivity_Ecker2015(c_e, T): + """ + Conductivity of LiPF6 in EC:DMC as a function of ion concentration [1, 2, 3]. + + References + ---------- + .. [1] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery i. determination of parameters." Journal of the + Electrochemical Society 162.9 (2015): A1836-A1848. + .. [2] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of + a lithium-ion battery ii. model validation." Journal of The Electrochemical + Society 162.9 (2015): A1849-A1857. + .. [3] Richardson, Giles, et. al. "Generalised single particle models for + high-rate operation of graded lithium-ion electrodes: Systematic derivation + and validation." Electrochemica Acta 339 (2020): 135862 + + Parameters + ---------- + c_e: :class:`pybamm.Symbol` + Dimensional electrolyte concentration + T: :class:`pybamm.Symbol` + Dimensional temperature + + Returns + ------- + :class:`pybamm.Symbol` + Solid diffusivity + """ + + # mol/m^3 to mol/l + cm = 1e-3 * c_e + + # value at T = 296K + sigma_e_296 = 0.2667 * cm**3 - 1.2983 * cm**2 + 1.7919 * cm + 0.1726 + + # add temperature dependence + E_k_e = 1.71e4 + C = 296 * pybamm.exp(E_k_e / (pybamm.constants.R * 296)) + sigma_e = C * sigma_e_296 * pybamm.exp(-E_k_e / (pybamm.constants.R * T)) / T + + return sigma_e + + +# Call dict via a function to avoid errors when editing in place +def get_parameter_values(): + """ + Parameters for a graphite half-cell based on a Kokam SLPB 75106100 cell, from papers + + Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of a + lithium-ion battery I. determination of parameters." Journal of the + Electrochemical Society 162.9 (2015): A1836-A1848. + + Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of a + lithium-ion battery II. Model validation." Journal of The Electrochemical + Society 162.9 (2015): A1849-A1857. + + The tab placement parameters are taken from measurements in + + Hales, Alastair, et al. "The cell cooling coefficient: a standard to define heat + rejection from lithium-ion batteries." Journal of The Electrochemical Society + 166.12 (2019): A2383. + + The thermal material properties are for a 5 Ah power pouch cell by Kokam. The data + are extracted from + + Zhao, Y., et al. "Modeling the effects of thermal gradients induced by tab and + surface cooling on lithium ion cell performance."" Journal of The + Electrochemical Society, 165.13 (2018): A3169-A3178. + + Graphite electrode parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + The fits to data for the electrode and electrolyte properties are those provided + by Dr. Simon O'Kane in the paper: + + Richardson, Giles, et. al. "Generalised single particle models for high-rate + operation of graded lithium-ion electrodes: Systematic derivation and + validation." Electrochemica Acta 339 (2020): 135862 + + SEI parameters are example parameters for SEI growth from the papers: + + + Ramadass, P., Haran, B., Gomadam, P. M., White, R., & Popov, B. N. (2004). + Development of first principles capacity fade model for Li-ion cells. Journal of + the Electrochemical Society, 151(2), A196-A203. + + Ploehn, H. J., Ramadass, P., & White, R. E. (2004). Solvent diffusion model for + aging of lithium-ion battery cells. Journal of The Electrochemical Society, + 151(3), A456-A462. + + Single, F., Latz, A., & Horstmann, B. (2018). Identifying the mechanism of + continued growth of the solid-electrolyte interphase. ChemSusChem, 11(12), + 1950-1955. + + Safari, M., Morcrette, M., Teyssot, A., & Delacour, C. (2009). Multimodal + Physics- Based Aging Model for Life Prediction of Li-Ion Batteries. Journal of + The Electrochemical Society, 156(3), + + Yang, X., Leng, Y., Zhang, G., Ge, S., Wang, C. (2017). Modeling of lithium + plating induced aging of lithium-ion batteries: Transition from linear to + nonlinear aging. Journal of Power Sources, 360, 28-40. + + Note: this parameter set does not claim to be representative of the true parameter + values. Instead these are parameter values that were used to fit SEI models to + observed experimental data in the referenced papers. + """ + + return { + "chemistry": "lithium_ion", + # sei + "Ratio of lithium moles to SEI moles": 2.0, + "Inner SEI reaction proportion": 0.5, + "Inner SEI partial molar volume [m3.mol-1]": 9.585e-05, + "Outer SEI partial molar volume [m3.mol-1]": 9.585e-05, + "SEI reaction exchange current density [A.m-2]": 1.5e-07, + "SEI resistivity [Ohm.m]": 200000.0, + "Outer SEI solvent diffusivity [m2.s-1]": 2.5000000000000002e-22, + "Bulk solvent concentration [mol.m-3]": 2636.0, + "Inner SEI open-circuit potential [V]": 0.1, + "Outer SEI open-circuit potential [V]": 0.8, + "Inner SEI electron conductivity [S.m-1]": 8.95e-14, + "Inner SEI lithium interstitial diffusivity [m2.s-1]": 1e-20, + "Lithium interstitial reference concentration [mol.m-3]": 15.0, + "Initial inner SEI thickness [m]": 2.5e-09, + "Initial outer SEI thickness [m]": 2.5e-09, + "EC initial concentration in electrolyte [mol.m-3]": 4541.0, + "EC diffusivity [m2.s-1]": 2e-18, + "SEI kinetic rate constant [m.s-1]": 1e-12, + "SEI open-circuit potential [V]": 0.4, + "SEI growth activation energy [J.mol-1]": 0.0, + "Positive electrode reaction-driven LAM factor [m3.mol-1]": 0.0, + # cell + "Positive current collector thickness [m]": 1.4e-05, + "Positive electrode thickness [m]": 7.4e-05, + "Separator thickness [m]": 2e-05, + "Electrode height [m]": 0.101, + "Electrode width [m]": 0.085, + "Positive tab width [m]": 0.007, + "Positive tab centre y-coordinate [m]": 0.0045, + "Positive tab centre z-coordinate [m]": 0.101, + "Cell cooling surface area [m2]": 0.0172, + "Cell volume [m3]": 1.52e-06, + "Positive current collector conductivity [S.m-1]": 58411000.0, + "Positive current collector density [kg.m-3]": 8933.0, + "Positive current collector specific heat capacity [J.kg-1.K-1]": 385.0, + "Positive current collector thermal conductivity [W.m-1.K-1]": 398.0, + "Nominal cell capacity [A.h]": 0.15625, + "Current function [A]": 0.15652, + "Contact resistance [Ohm]": 0, + # positive electrode + "Positive electrode conductivity [S.m-1]": 14.0, + "Maximum concentration in positive electrode [mol.m-3]": 31920.0, + "Positive electrode diffusivity [m2.s-1]": graphite_diffusivity_Ecker2015, + "Positive electrode OCP [V]": graphite_ocp_Ecker2015, + "Positive electrode porosity": 0.329, + "Positive electrode active material volume fraction": 0.372403, + "Positive particle radius [m]": 1.37e-05, + "Positive electrode Bruggeman coefficient (electrolyte)": 1.6372789338386007, + "Positive electrode Bruggeman coefficient (electrode)": 0.0, + "Positive electrode exchange-current density [A.m-2]" + "": graphite_electrolyte_exchange_current_density_Ecker2015, + "Positive electrode density [kg.m-3]": 1555.0, + "Positive electrode specific heat capacity [J.kg-1.K-1]": 1437.0, + "Positive electrode thermal conductivity [W.m-1.K-1]": 1.58, + "Positive electrode OCP entropic change [V.K-1]": 0.0, + # separator + "Separator porosity": 0.508, + "Separator Bruggeman coefficient (electrolyte)": 1.9804586773134945, + "Separator density [kg.m-3]": 1017.0, + "Separator specific heat capacity [J.kg-1.K-1]": 1978.0, + "Separator thermal conductivity [W.m-1.K-1]": 0.34, + # electrolyte + "Initial concentration in electrolyte [mol.m-3]": 1000.0, + "Cation transference number": 0.26, + "Thermodynamic factor": 1.0, + "Electrolyte diffusivity [m2.s-1]": electrolyte_diffusivity_Ecker2015, + "Electrolyte conductivity [S.m-1]": electrolyte_conductivity_Ecker2015, + # experiment + "Reference temperature [K]": 296.15, + "Positive current collector surface heat transfer coefficient [W.m-2.K-1]" + "": 10.0, + "Positive tab heat transfer coefficient [W.m-2.K-1]": 10.0, + "Edge heat transfer coefficient [W.m-2.K-1]": 10.0, + "Total heat transfer coefficient [W.m-2.K-1]": 10.0, + "Ambient temperature [K]": 298.15, + "Number of electrodes connected in parallel to make a cell": 1.0, + "Number of cells connected in series to make a battery": 1.0, + "Lower voltage cut-off [V]": 2.5, + "Upper voltage cut-off [V]": 4.2, + "Initial concentration in positive electrode [mol.m-3]": 26120.05, + "Initial temperature [K]": 298.15, + # citations + "citations": [ + "Ecker2015i", + "Ecker2015ii", + "Zhao2018", + "Hales2019", + "Richardson2020", + ], + } diff --git a/pybamm/models/full_battery_models/base_battery_model.py b/pybamm/models/full_battery_models/base_battery_model.py index 440a129bd2..1cbed0d11b 100644 --- a/pybamm/models/full_battery_models/base_battery_model.py +++ b/pybamm/models/full_battery_models/base_battery_model.py @@ -292,13 +292,19 @@ def __init__(self, extra_options): # The "SEI film resistance" option will still be overridden by extra_options if # provided - # Change the default for particle mechanics based on which SEI on cracks and LAM - # options are provided - # return "false" and "none" respectively if options not given + # Change the default for particle mechanics based on which half-cell, + # SEI on cracks and LAM options are provided + # return "false", "false" and "none" respectively if options not given + half_cell_option = extra_options.get("half-cell", "false") SEI_cracks_option = extra_options.get("SEI on cracks", "false") LAM_opt = extra_options.get("loss of active material", "none") - if SEI_cracks_option == "true": - if "stress-driven" in LAM_opt or "stress and reaction-driven" in LAM_opt: + if "true" in SEI_cracks_option: + if half_cell_option == "true": + default_options["particle mechanics"] = ( # is this right? + "none", + "swelling and cracking", + ) + elif "stress-driven" in LAM_opt or "stress and reaction-driven" in LAM_opt: default_options["particle mechanics"] = ( "swelling and cracking", "swelling only", @@ -342,6 +348,7 @@ def __init__(self, extra_options): default_options["surface form"] = "algebraic" # The "surface form" option will still be overridden by # extra_options if provided + # Change default SEI model based on which lithium plating option is provided # return "none" if option not given plating_option = extra_options.get("lithium plating", "none") @@ -541,12 +548,15 @@ def __init__(self, extra_options): in [ "intercalation kinetics", "interface utilisation", + "lithium plating", "loss of active material", "open-circuit potential", "particle", "particle mechanics", "particle phases", "particle size", + "SEI", + "SEI on cracks", "stress-induced diffusion", ] and isinstance(value, tuple) diff --git a/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py b/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py index ecc173f97e..c0b5d1935c 100644 --- a/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py +++ b/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py @@ -97,10 +97,16 @@ def set_active_material_submodel(self): ) def set_sei_submodel(self): - self.submodels["sei"] = pybamm.sei.NoSEI(self.param, self.options) + for domain in ["negative", "positive"]: + self.submodels[f"{domain} sei"] = pybamm.sei.NoSEI( + self.param, domain, self.options + ) def set_lithium_plating_submodel(self): - self.submodels["lithium plating"] = pybamm.lithium_plating.NoPlating(self.param) + for domain in ["negative", "positive"]: + self.submodels[ + f"{domain} lithium plating" + ] = pybamm.lithium_plating.NoPlating(self.param, domain) def set_total_interface_submodel(self): self.submodels["total interface"] = pybamm.interface.TotalInterfacialCurrent( diff --git a/pybamm/models/full_battery_models/lithium_ion/base_lithium_ion_model.py b/pybamm/models/full_battery_models/lithium_ion/base_lithium_ion_model.py index cc615dacf7..22bae5510e 100644 --- a/pybamm/models/full_battery_models/lithium_ion/base_lithium_ion_model.py +++ b/pybamm/models/full_battery_models/lithium_ion/base_lithium_ion_model.py @@ -159,13 +159,16 @@ def set_degradation_variables(self): # Lithium lost to side reactions # Different way of measuring LLI but should give same value - n_Li_lost_sei = self.variables["Loss of lithium to SEI [mol]"] - n_Li_lost_reactions = n_Li_lost_sei - if "negative electrode" in domains: + n_Li_lost_neg_sei = self.variables["Loss of lithium to negative SEI [mol]"] + n_Li_lost_pos_sei = self.variables["Loss of lithium to positive SEI [mol]"] + n_Li_lost_reactions = n_Li_lost_neg_sei + n_Li_lost_pos_sei + for domain in domains: n_Li_lost_sei_cracks = self.variables[ - "Loss of lithium to SEI on cracks [mol]" + f"Loss of lithium to {domain} SEI on cracks [mol]" + ] + n_Li_lost_pl = self.variables[ + f"Loss of lithium to {domain} lithium plating [mol]" ] - n_Li_lost_pl = self.variables["Loss of lithium to lithium plating [mol]"] n_Li_lost_reactions += n_Li_lost_sei_cracks + n_Li_lost_pl self.variables.update( @@ -197,8 +200,10 @@ def set_summary_variables(self): "Total lithium lost [mol]", "Total lithium lost from particles [mol]", "Total lithium lost from electrolyte [mol]", - "Loss of lithium to SEI [mol]", - "Loss of capacity to SEI [A.h]", + "Loss of lithium to negative SEI [mol]", + "Loss of capacity to negative SEI [A.h]", + "Loss of lithium to positive SEI [mol]", + "Loss of capacity to positive SEI [A.h]", "Total lithium lost to side reactions [mol]", "Total capacity lost to side reactions [A.h]", # Resistance @@ -210,16 +215,20 @@ def set_summary_variables(self): "Negative electrode capacity [A.h]", "Loss of active material in negative electrode [%]", "Total lithium in negative electrode [mol]", - "Loss of lithium to lithium plating [mol]", - "Loss of capacity to lithium plating [A.h]", - "Loss of lithium to SEI on cracks [mol]", - "Loss of capacity to SEI on cracks [A.h]", + "Loss of lithium to negative lithium plating [mol]", + "Loss of capacity to negative lithium plating [A.h]", + "Loss of lithium to negative SEI on cracks [mol]", + "Loss of capacity to negative SEI on cracks [A.h]", ] if self.options.electrode_types["positive"] == "porous": summary_variables += [ "Positive electrode capacity [A.h]", "Loss of active material in positive electrode [%]", "Total lithium in positive electrode [mol]", + "Loss of lithium to positive lithium plating [mol]", + "Loss of capacity to positive lithium plating [A.h]", + "Loss of lithium to positive SEI on cracks [mol]", + "Loss of capacity to positive SEI on cracks [A.h]", ] self.summary_variables = summary_variables @@ -243,56 +252,75 @@ def set_open_circuit_potential_submodel(self): ) def set_sei_submodel(self): - if self.options.electrode_types["negative"] == "planar": - reaction_loc = "interface" - elif self.options["x-average side reactions"] == "true": - reaction_loc = "x-average" - else: - reaction_loc = "full electrode" - - phases = self.options.phases["negative"] - for phase in phases: - if self.options["SEI"] == "none": - submodel = pybamm.sei.NoSEI(self.param, self.options, phase) - elif self.options["SEI"] == "constant": - submodel = pybamm.sei.ConstantSEI(self.param, self.options, phase) + for domain in ["negative", "positive"]: + if self.options.electrode_types[domain] == "planar": + reaction_loc = "interface" + elif self.options["x-average side reactions"] == "true": + reaction_loc = "x-average" else: - submodel = pybamm.sei.SEIGrowth( - self.param, reaction_loc, self.options, phase, cracks=False - ) - self.submodels[f"{phase} sei"] = submodel - # Do not set "sei on cracks" submodel for half-cells - # For full cells, "sei on cracks" submodel must be set, even if it is zero - if reaction_loc != "interface": - if ( - self.options["SEI"] in ["none", "constant"] - or self.options["SEI on cracks"] == "false" - ): - submodel = pybamm.sei.NoSEI( - self.param, self.options, phase, cracks=True + reaction_loc = "full electrode" + + phases = self.options.phases[domain] + for phase in phases: + if self.options["SEI"] == "none": + submodel = pybamm.sei.NoSEI(self.param, domain, self.options, phase) + elif self.options["SEI"] == "constant": + submodel = pybamm.sei.ConstantSEI( + self.param, domain, self.options, phase ) else: submodel = pybamm.sei.SEIGrowth( - self.param, reaction_loc, self.options, phase, cracks=True + self.param, + domain, + reaction_loc, + self.options, + phase, + cracks=False, ) - self.submodels[f"{phase} sei on cracks"] = submodel + self.submodels[f"{domain} {phase} sei"] = submodel + # Do not set "sei on cracks" submodel for a planar electrode. For porous + # electrodes, "sei on cracks" submodel must be set, even if it is zero + if reaction_loc != "interface": + if ( + self.options["SEI"] in ["none", "constant"] + or self.options["SEI on cracks"] == "false" + ): + submodel = pybamm.sei.NoSEI( + self.param, domain, self.options, phase, cracks=True + ) + else: + submodel = pybamm.sei.SEIGrowth( + self.param, + domain, + reaction_loc, + self.options, + phase, + cracks=True, + ) + self.submodels[f"{domain} {phase} sei on cracks"] = submodel - if len(phases) > 1: - self.submodels["total sei"] = pybamm.sei.TotalSEI(self.param, self.options) - self.submodels["total sei on cracks"] = pybamm.sei.TotalSEI( - self.param, self.options, cracks=True - ) + if len(phases) > 1: + self.submodels[f"{domain} total sei"] = pybamm.sei.TotalSEI( + self.param, self.options + ) + self.submodels[f"{domain} total sei on cracks"] = pybamm.sei.TotalSEI( + self.param, self.options, cracks=True + ) def set_lithium_plating_submodel(self): - if self.options["lithium plating"] == "none": - self.submodels["lithium plating"] = pybamm.lithium_plating.NoPlating( - self.param, self.options - ) - else: - x_average = self.options["x-average side reactions"] == "true" - self.submodels["lithium plating"] = pybamm.lithium_plating.Plating( - self.param, x_average, self.options - ) + domains = [d for d in self.options.whole_cell_domains if d != "separator"] + for domain in domains: + if self.options["lithium plating"] == "none": + self.submodels[ + f"{domain} lithium plating" + ] = pybamm.lithium_plating.NoPlating(self.param, domain, self.options) + else: + x_average = self.options["x-average side reactions"] == "true" + self.submodels[ + f"{domain} lithium plating" + ] = pybamm.lithium_plating.Plating( + self.param, domain, x_average, self.options + ) def set_total_interface_submodel(self): self.submodels["total interface"] = pybamm.interface.TotalInterfacialCurrent( diff --git a/pybamm/models/full_battery_models/lithium_metal/dfn.py b/pybamm/models/full_battery_models/lithium_metal/dfn.py index eb11345c90..923be6fbe9 100644 --- a/pybamm/models/full_battery_models/lithium_metal/dfn.py +++ b/pybamm/models/full_battery_models/lithium_metal/dfn.py @@ -29,7 +29,7 @@ def __init__( self, options=None, name="Doyle-Fuller-Newman lithium metal model", build=True ): options = options or {} - options["half-cell"] = "positive" + options["half-cell"] = "true" super().__init__(options, name, build=False) if build: diff --git a/pybamm/models/submodels/electrode/ohm/li_metal.py b/pybamm/models/submodels/electrode/ohm/li_metal.py index e03ed770ad..31cdc7284e 100644 --- a/pybamm/models/submodels/electrode/ohm/li_metal.py +++ b/pybamm/models/submodels/electrode/ohm/li_metal.py @@ -76,9 +76,10 @@ def set_initial_conditions(self, variables): self.initial_conditions = {delta_phi: delta_phi_init} def set_rhs(self, variables): + Domain = self.domain.capitalize() if self.options["surface form"] == "differential": j_pl = variables["Lithium metal plating current density [A.m-2]"] - j_sei = variables["SEI interfacial current density [A.m-2]"] + j_sei = variables[f"{Domain} SEI interfacial current density [A.m-2]"] sum_j = j_pl + j_sei i_cc = variables["Current collector current density [A.m-2]"] @@ -91,9 +92,10 @@ def set_rhs(self, variables): self.rhs[delta_phi] = 1 / C_dl * (i_cc - sum_j) def set_algebraic(self, variables): + Domain = self.domain.capitalize() if self.options["surface form"] != "differential": # also catches "false" j_pl = variables["Lithium metal plating current density [A.m-2]"] - j_sei = variables["SEI interfacial current density [A.m-2]"] + j_sei = variables[f"{Domain} SEI interfacial current density [A.m-2]"] sum_j = j_pl + j_sei i_cc = variables["Current collector current density [A.m-2]"] diff --git a/pybamm/models/submodels/interface/lithium_plating/base_plating.py b/pybamm/models/submodels/interface/lithium_plating/base_plating.py index 6d848b6b70..07cf25e302 100644 --- a/pybamm/models/submodels/interface/lithium_plating/base_plating.py +++ b/pybamm/models/submodels/interface/lithium_plating/base_plating.py @@ -26,56 +26,44 @@ class BasePlating(BaseInterface): how to model it". Physical Chemistry: Chemical Physics, 24:7909, 2022 """ - def __init__(self, param, options=None): + def __init__(self, domain, param, options=None): reaction = "lithium plating" - domain = "negative" super().__init__(param, domain, reaction, options=options) def get_coupled_variables(self, variables): # Update some common variables + domain, Domain = self.domain_Domain - if self.options.electrode_types["negative"] == "porous": - j_plating = variables["Lithium plating interfacial current density [A.m-2]"] + if self.options.electrode_types[domain] == "porous": + j_plating = variables[ + f"{Domain} lithium plating interfacial current density [A.m-2]" + ] j_plating_av = variables[ - "X-averaged lithium plating interfacial current density [A.m-2]" + f"X-averaged {domain} lithium plating " + "interfacial current density [A.m-2]" ] if self.options.negative["particle phases"] == "1": - a = variables["Negative electrode surface area to volume ratio [m-1]"] + a = variables[f"{Domain} electrode surface area to volume ratio [m-1]"] else: a = variables[ - "Negative electrode primary surface area to volume ratio [m-1]" + f"{Domain} electrode primary surface area to volume ratio [m-1]" ] a_j_plating = a * j_plating a_j_plating_av = pybamm.x_average(a_j_plating) variables.update( { - "Negative electrode lithium plating interfacial current " + f"{Domain} electrode lithium plating interfacial current " "density [A.m-2]": j_plating, - "X-averaged negative electrode lithium plating " + f"X-averaged {domain} electrode lithium plating " "interfacial current density [A.m-2]": j_plating_av, - "Lithium plating volumetric " + f"{Domain} lithium plating volumetric " "interfacial current density [A.m-3]": a_j_plating, - "X-averaged lithium plating volumetric " + f"X-averaged {domain} lithium plating volumetric " "interfacial current density [A.m-3]": a_j_plating_av, } ) - zero_av = pybamm.PrimaryBroadcast(0, "current collector") - zero = pybamm.FullBroadcast(0, "positive electrode", "current collector") - variables.update( - { - "X-averaged positive electrode lithium plating " - "interfacial current density [A.m-2]": zero_av, - "X-averaged positive electrode lithium plating volumetric " - "interfacial current density [A.m-3]": zero_av, - "Positive electrode lithium plating " - "interfacial current density [A.m-2]": zero, - "Positive electrode lithium plating volumetric " - "interfacial current density [A.m-3]": zero, - } - ) - variables.update( self._get_standard_volumetric_current_density_variables(variables) ) @@ -96,6 +84,7 @@ def _get_standard_concentration_variables(self, c_plated_Li, c_dead_Li): The variables which can be derived from the plated lithium thickness. """ param = self.param + domain, Domain = self.domain_Domain # Set scales to one for the "no plating" model so that they are not required # by parameter values in general @@ -116,18 +105,19 @@ def _get_standard_concentration_variables(self, c_plated_Li, c_dead_Li): Q_dead_Li = c_dead_Li_av * param.n.L * param.L_y * param.L_z variables = { - "Lithium plating concentration [mol.m-3]": c_plated_Li, - "X-averaged lithium plating concentration [mol.m-3]": c_plated_Li_av, - "Dead lithium concentration [mol.m-3]": c_dead_Li, - "X-averaged dead lithium concentration [mol.m-3]": c_dead_Li_av, - "Lithium plating thickness [m]": L_plated_Li, - "X-averaged lithium plating thickness [m]": L_plated_Li_av, - "Dead lithium thickness [m]": L_dead_Li, - "X-averaged dead lithium thickness [m]": L_dead_Li_av, - "Loss of lithium to lithium plating [mol]": (Q_plated_Li + Q_dead_Li), - "Loss of capacity to lithium plating [A.h]": (Q_plated_Li + Q_dead_Li) - * param.F - / 3600, + f"{Domain} lithium plating concentration [mol.m-3]": c_plated_Li, + f"X-averaged {domain} lithium plating " + "concentration [mol.m-3]": c_plated_Li_av, + f"{Domain} dead lithium concentration [mol.m-3]": c_dead_Li, + f"X-averaged {domain} dead lithium concentration [mol.m-3]": c_dead_Li_av, + f"{Domain} lithium plating thickness [m]": L_plated_Li, + f"X-averaged {domain} lithium plating thickness [m]": L_plated_Li_av, + f"{Domain} Dead lithium thickness [m]": L_dead_Li, + f"X-averaged {domain} dead lithium thickness [m]": L_dead_Li_av, + f"Loss of lithium to {domain} lithium plating " + "[mol]": (Q_plated_Li + Q_dead_Li), + f"Loss of capacity to {domain} lithium plating " + "[A.h]": (Q_plated_Li + Q_dead_Li) * param.F / 3600, } return variables @@ -145,13 +135,13 @@ def _get_standard_reaction_variables(self, j_stripping): variables : dict The variables which can be derived from the plated lithium thickness. """ - # Set scales to one for the "no plating" model so that they are not required - # by parameter values in general + domain, Domain = self.domain_Domain j_stripping_av = pybamm.x_average(j_stripping) variables = { - "Lithium plating interfacial current density [A.m-2]": j_stripping, - "X-averaged lithium plating " + f"{Domain} lithium plating interfacial current density " + "[A.m-2]": j_stripping, + f"X-averaged {domain} lithium plating " "interfacial current density [A.m-2]": j_stripping_av, } diff --git a/pybamm/models/submodels/interface/lithium_plating/no_plating.py b/pybamm/models/submodels/interface/lithium_plating/no_plating.py index 1a2f59808a..ad7fd7301a 100644 --- a/pybamm/models/submodels/interface/lithium_plating/no_plating.py +++ b/pybamm/models/submodels/interface/lithium_plating/no_plating.py @@ -16,12 +16,12 @@ class NoPlating(BasePlating): A dictionary of options to be passed to the model. """ - def __init__(self, param, options=None): - super().__init__(param, options=options) + def __init__(self, domain, param, options=None): + super().__init__(param, domain, options=options) def get_fundamental_variables(self): zero = pybamm.FullBroadcast( - pybamm.Scalar(0), "negative electrode", "current collector" + pybamm.Scalar(0), f"{self.domain} electrode", "current collector" ) variables = self._get_standard_concentration_variables(zero, zero) variables.update(self._get_standard_overpotential_variables(zero)) diff --git a/pybamm/models/submodels/interface/lithium_plating/plating.py b/pybamm/models/submodels/interface/lithium_plating/plating.py index c519115fc8..1ce898a737 100644 --- a/pybamm/models/submodels/interface/lithium_plating/plating.py +++ b/pybamm/models/submodels/interface/lithium_plating/plating.py @@ -28,35 +28,36 @@ class Plating(BasePlating): how to model it". Physical Chemistry: Chemical Physics, 24:7909, 2022 """ - def __init__(self, param, x_average, options): - super().__init__(param, options) + def __init__(self, param, domain, x_average, options): + super().__init__(param, domain, options=options) self.x_average = x_average pybamm.citations.register("OKane2020") pybamm.citations.register("OKane2022") def get_fundamental_variables(self): + domain, Domain = self.domain_Domain if self.x_average is True: c_plated_Li_av = pybamm.Variable( - "X-averaged lithium plating concentration [mol.m-3]", + f"X-averaged {domain} lithium plating concentration [mol.m-3]", domain="current collector", scale=self.param.c_Li_typ, ) - c_plated_Li = pybamm.PrimaryBroadcast(c_plated_Li_av, "negative electrode") + c_plated_Li = pybamm.PrimaryBroadcast(c_plated_Li_av, f"{domain} electrode") c_dead_Li_av = pybamm.Variable( - "X-averaged dead lithium concentration [mol.m-3]", + f"X-averaged {domain} dead lithium concentration [mol.m-3]", domain="current collector", ) - c_dead_Li = pybamm.PrimaryBroadcast(c_dead_Li_av, "negative electrode") + c_dead_Li = pybamm.PrimaryBroadcast(c_dead_Li_av, f"{domain} electrode") else: c_plated_Li = pybamm.Variable( - "Lithium plating concentration [mol.m-3]", - domain="negative electrode", + f"{Domain} lithium plating concentration [mol.m-3]", + domain=f"{domain} electrode", auxiliary_domains={"secondary": "current collector"}, scale=self.param.c_Li_typ, ) c_dead_Li = pybamm.Variable( - "Dead lithium concentration [mol.m-3]", - domain="negative electrode", + f"{Domain} dead lithium concentration [mol.m-3]", + domain=f"{domain} electrode", auxiliary_domains={"secondary": "current collector"}, ) @@ -66,11 +67,12 @@ def get_fundamental_variables(self): def get_coupled_variables(self, variables): param = self.param - delta_phi = variables["Negative electrode surface potential difference [V]"] - c_e_n = variables["Negative electrolyte concentration [mol.m-3]"] - T = variables["Negative electrode temperature [K]"] - eta_sei = variables["SEI film overpotential [V]"] - c_plated_Li = variables["Lithium plating concentration [mol.m-3]"] + Domain = self.domain.capitalize() + delta_phi = variables[f"{Domain} electrode surface potential difference [V]"] + c_e_n = variables[f"{Domain} electrolyte concentration [mol.m-3]"] + T = variables[f"{Domain} electrode temperature [K]"] + eta_sei = variables[f"{Domain} SEI film overpotential [V]"] + c_plated_Li = variables[f" {Domain} lithium plating concentration [mol.m-3]"] j0_stripping = param.j0_stripping(c_e_n, c_plated_Li, T) j0_plating = param.j0_plating(c_e_n, c_plated_Li, T) @@ -99,23 +101,27 @@ def get_coupled_variables(self, variables): return variables def set_rhs(self, variables): + domain, Domain = self.domain_Domain if self.x_average is True: c_plated_Li = variables[ - "X-averaged lithium plating concentration [mol.m-3]" + f"X-averaged {domain} lithium plating concentration [mol.m-3]" + ] + c_dead_Li = variables[ + f"X-averaged {domain} dead lithium concentration [mol.m-3]" ] - c_dead_Li = variables["X-averaged dead lithium concentration [mol.m-3]"] a_j_stripping = variables[ - "X-averaged lithium plating volumetric " + f"X-averaged {domain} lithium plating volumetric " "interfacial current density [A.m-3]" ] - L_sei = variables["X-averaged total SEI thickness [m]"] + L_sei = variables[f"X-averaged {domain} total SEI thickness [m]"] else: - c_plated_Li = variables["Lithium plating concentration [mol.m-3]"] - c_dead_Li = variables["Dead lithium concentration [mol.m-3]"] + c_plated_Li = variables[f"{Domain} lithium plating concentration [mol.m-3]"] + c_dead_Li = variables[f"{Domain} dead lithium concentration [mol.m-3]"] a_j_stripping = variables[ - "Lithium plating volumetric interfacial current density [A.m-3]" + f"{Domain} lithium plating volumetric " + "interfacial current density [A.m-3]" ] - L_sei = variables["Total SEI thickness [m]"] + L_sei = variables[f"{Domain} total SEI thickness [m]"] # In the partially reversible plating model, coupling term turns reversible # lithium into dead lithium. In other plating models, it is zero. @@ -131,14 +137,17 @@ def set_rhs(self, variables): } def set_initial_conditions(self, variables): + domain, Domain = self.domain_Domain if self.x_average is True: c_plated_Li = variables[ - "X-averaged lithium plating concentration [mol.m-3]" + f"X-averaged {domain} lithium plating concentration [mol.m-3]" + ] + c_dead_Li = variables[ + f"X-averaged {domain} dead lithium concentration [mol.m-3]" ] - c_dead_Li = variables["X-averaged dead lithium concentration [mol.m-3]"] else: - c_plated_Li = variables["Lithium plating concentration [mol.m-3]"] - c_dead_Li = variables["Dead lithium concentration [mol.m-3]"] + c_plated_Li = variables[f"{Domain} lithium plating concentration [mol.m-3]"] + c_dead_Li = variables[f"{domain} dead lithium concentration [mol.m-3]"] c_plated_Li_0 = self.param.c_plated_Li_0 zero = pybamm.Scalar(0) diff --git a/pybamm/models/submodels/interface/sei/base_sei.py b/pybamm/models/submodels/interface/sei/base_sei.py index 6b08214ff4..9c57721d99 100644 --- a/pybamm/models/submodels/interface/sei/base_sei.py +++ b/pybamm/models/submodels/interface/sei/base_sei.py @@ -20,53 +20,37 @@ class BaseModel(BaseInterface): Whether this is a submodel for standard SEI or SEI on cracks """ - def __init__(self, param, options, phase="primary", cracks=False): + def __init__(self, param, domain, options, phase="primary", cracks=False): if cracks is True: reaction = "SEI on cracks" else: reaction = "SEI" - domain = "negative" super().__init__(param, domain, reaction, options=options, phase=phase) def get_coupled_variables(self, variables): # Update some common variables - zero_av = pybamm.PrimaryBroadcast(0, "current collector") - zero = pybamm.FullBroadcast(0, "positive electrode", "current collector") + domain, Domain = self.domain_Domain if self.reaction_loc != "interface": + j_sei_av = variables[ + f"X-averaged {domain} electrode {self.reaction_name}interfacial" + " current density [A.m-2]" + ] + j_sei = variables[ + f"{Domain} electrode {self.reaction_name}interfacial current" + " density [A.m-2]" + ] variables.update( { - f"X-averaged negative electrode {self.reaction_name}interfacial " - "current density": variables[ - f"X-averaged {self.reaction_name}interfacial current density" - ], - f"Negative electrode {self.reaction_name}interfacial current " - "density": variables[ - f"{self.reaction_name}interfacial current density" - ], - f"Negative electrode {self.reaction_name}interfacial current " - "density [A.m-2]": variables[ - f"{self.reaction_name}interfacial current density [A.m-2]" - ], + f"X-averaged {domain} electrode {self.reaction_name}interfacial " + "current density [A.m-2]": j_sei_av, + f"{Domain} electrode {self.reaction_name}interfacial current " + "density [A.m-2]": j_sei, } ) - variables.update( - self._get_standard_volumetric_current_density_variables(variables) - ) variables.update( - { - f"X-averaged positive electrode {self.reaction} " - "interfacial current density": zero_av, - f"Positive electrode {self.reaction} " - "interfacial current density": zero, - f"Positive electrode {self.reaction} " - "interfacial current density [A.m-2]": zero, - f"X-averaged positive electrode {self.reaction} " - "volumetric interfacial current density": zero_av, - f"Positive electrode {self.reaction} " - "volumetric interfacial current density": zero, - } + self._get_standard_volumetric_current_density_variables(variables) ) return variables @@ -88,9 +72,10 @@ def _get_standard_thickness_variables(self, L_inner, L_outer): variables : dict The variables which can be derived from the SEI thicknesses. """ + domain, Domain = self.domain_Domain variables = { - f"Inner {self.reaction_name}thickness [m]": L_inner, - f"Outer {self.reaction_name}thickness [m]": L_outer, + f"{Domain} inner {self.reaction_name}thickness [m]": L_inner, + f"{Domain} outer {self.reaction_name}thickness [m]": L_outer, } if self.reaction_loc != "interface": @@ -98,8 +83,10 @@ def _get_standard_thickness_variables(self, L_inner, L_outer): L_outer_av = pybamm.x_average(L_outer) variables.update( { - f"X-averaged inner {self.reaction_name}thickness [m]": L_inner_av, - f"X-averaged outer {self.reaction_name}thickness [m]": L_outer_av, + f"X-averaged {domain} inner {self.reaction_name}" + "thickness [m]": L_inner_av, + f"X-averaged {domain} outer {self.reaction_name}" + "thickness [m]": L_outer_av, } ) # Get variables related to the total thickness @@ -110,7 +97,7 @@ def _get_standard_thickness_variables(self, L_inner, L_outer): def _get_standard_total_thickness_variables(self, L_sei): """Update variables related to total SEI thickness.""" - domain = self.domain + domain, Domain = self.domain_Domain if isinstance(self, pybamm.sei.NoSEI): R_sei = 1 @@ -118,15 +105,16 @@ def _get_standard_total_thickness_variables(self, L_sei): R_sei = self.phase_param.R_sei variables = { - f"{self.reaction_name}[m]": L_sei, - f"Total {self.reaction_name}thickness [m]": L_sei, + f"{Domain} {self.reaction_name}[m]": L_sei, + f"Total {domain} {self.reaction_name}thickness [m]": L_sei, } if self.reaction_loc != "interface": L_sei_av = pybamm.x_average(L_sei) variables.update( { - f"X-averaged {self.reaction_name}thickness [m]": L_sei_av, - f"X-averaged total {self.reaction_name}thickness [m]": L_sei_av, + f"X-averaged {domain} {self.reaction_name}thickness [m]": L_sei_av, + f"X-averaged total {domain} {self.reaction_name}" + "thickness [m]": L_sei_av, } ) if self.reaction == "SEI": @@ -140,7 +128,7 @@ def _get_standard_total_thickness_variables(self, L_sei): def _get_standard_concentration_variables(self, variables): """Update variables related to the SEI concentration.""" - Domain = self.domain.capitalize() + domain, Domain = self.domain_Domain phase_param = self.phase_param reaction_name = self.reaction_name @@ -180,8 +168,8 @@ def _get_standard_concentration_variables(self, variables): ) if self.reaction == "SEI": - L_inner = variables[f"Inner {reaction_name}thickness [m]"] - L_outer = variables[f"Outer {reaction_name}thickness [m]"] + L_inner = variables[f"{Domain} inner {reaction_name}thickness [m]"] + L_outer = variables[f"{Domain} outer {reaction_name}thickness [m]"] n_inner = L_inner * L_to_n_inner # inner SEI concentration n_outer = L_outer * L_to_n_outer # outer SEI concentration @@ -209,24 +197,25 @@ def _get_standard_concentration_variables(self, variables): variables.update( { - f"Inner {reaction_name}concentration [mol.m-3]": n_inner, - f"X-averaged inner {reaction_name}" + f"{Domain} inner {reaction_name}concentration [mol.m-3]": n_inner, + f"X-averaged {domain} inner {reaction_name}" "concentration [mol.m-3]": n_inner_av, - f"Outer {reaction_name}concentration [mol.m-3]": n_outer, - f"X-averaged outer {reaction_name}" + f"{Domain} outer {reaction_name}concentration [mol.m-3]": n_outer, + f"X-averaged {domain} outer {reaction_name}" "concentration [mol.m-3]": n_outer_av, - f"{reaction_name}concentration [mol.m-3]": n_SEI, - f"X-averaged {reaction_name}concentration [mol.m-3]": n_SEI_xav, - f"Loss of lithium to {reaction_name}[mol]": Q_sei, - f"Loss of capacity to {reaction_name}[A.h]": Q_sei + f"{Domain} {reaction_name}concentration [mol.m-3]": n_SEI, + f"X-averaged {domain} {reaction_name}" + "concentration [mol.m-3]": n_SEI_xav, + f"Loss of lithium to {domain} {reaction_name}[mol]": Q_sei, + f"Loss of capacity to {domain} {reaction_name}[A.h]": Q_sei * self.param.F / 3600, } ) # Concentration variables are handled slightly differently for SEI on cracks elif self.reaction == "SEI on cracks": - L_inner_cr = variables[f"Inner {reaction_name}thickness [m]"] - L_outer_cr = variables[f"Outer {reaction_name}thickness [m]"] + L_inner_cr = variables[f"{Domain} inner {reaction_name}thickness [m]"] + L_outer_cr = variables[f"{Domain} outer {reaction_name}thickness [m]"] roughness = variables[f"{Domain} electrode roughness ratio"] n_inner_cr = L_inner_cr * L_to_n_inner * (roughness - 1) @@ -258,17 +247,19 @@ def _get_standard_concentration_variables(self, variables): variables.update( { - f"Inner {reaction_name}" "concentration [mol.m-3]": n_inner_cr, - f"X-averaged inner {reaction_name}" + f"{Domain} inner {reaction_name}" + "concentration [mol.m-3]": n_inner_cr, + f"X-averaged {domain} inner {reaction_name}" "concentration [mol.m-3]": n_inner_cr_av, - f"Outer {reaction_name}concentration [mol.m-3]": n_outer_cr, - f"X-averaged outer {reaction_name}" + f"{Domain} outer {reaction_name}" + "concentration [mol.m-3]": n_outer_cr, + f"X-averaged {domain} outer {reaction_name}" "concentration [mol.m-3]": n_outer_cr_av, - f"{reaction_name}" "concentration [mol.m-3]": n_SEI_cr, - f"X-averaged {reaction_name}" + f"{Domain} {reaction_name}" "concentration [mol.m-3]": n_SEI_cr, + f"X-averaged {domain} {reaction_name}" "concentration [mol.m-3]": n_SEI_cr_xav, - f"Loss of lithium to {reaction_name}[mol]": Q_sei_cr, - f"Loss of capacity to {reaction_name}[A.h]": Q_sei_cr + f"Loss of lithium to {domain} {reaction_name}[mol]": Q_sei_cr, + f"Loss of capacity to {domain} {reaction_name}[A.h]": Q_sei_cr * self.param.F / 3600, } @@ -293,25 +284,28 @@ def _get_standard_reaction_variables(self, j_inner, j_outer): variables : dict The variables which can be derived from the SEI currents. """ + domain, Domain = self.domain_Domain j_inner_av = pybamm.x_average(j_inner) j_outer_av = pybamm.x_average(j_outer) j_sei = j_inner + j_outer variables = { - f"Inner {self.reaction_name}interfacial current density [A.m-2]": j_inner, - f"X-averaged inner {self.reaction_name}" + f"{Domain} inner {self.reaction_name}" + "interfacial currentdensity [A.m-2]": j_inner, + f"X-averaged {domain} inner {self.reaction_name}" "interfacial current density [A.m-2]": j_inner_av, - f"Outer {self.reaction_name}interfacial current density [A.m-2]": j_outer, - f"X-averaged outer {self.reaction_name}" + f"{Domain} outer {self.reaction_name}" + "interfacial current density [A.m-2]": j_outer, + f"X-averaged {domain} outer {self.reaction_name}" "interfacial current density [A.m-2]": j_outer_av, - f"{self.reaction_name}interfacial current density [A.m-2]": j_sei, + f"{Domain} {self.reaction_name}interfacial current density [A.m-2]": j_sei, } if self.reaction_loc != "interface": j_sei_av = pybamm.x_average(j_sei) variables.update( { - f"X-averaged {self.reaction_name}" + f"X-averaged {domain} {self.reaction_name}" "interfacial current density [A.m-2]": j_sei_av, } ) diff --git a/pybamm/models/submodels/interface/sei/constant_sei.py b/pybamm/models/submodels/interface/sei/constant_sei.py index becaa511da..e6d9a58edd 100644 --- a/pybamm/models/submodels/interface/sei/constant_sei.py +++ b/pybamm/models/submodels/interface/sei/constant_sei.py @@ -23,8 +23,8 @@ class ConstantSEI(BaseModel): Phase of the particle (default is "primary") """ - def __init__(self, param, options, phase="primary"): - super().__init__(param, options=options, phase=phase) + def __init__(self, param, domain, options, phase="primary"): + super().__init__(param, domain, options=options, phase=phase) if self.options.electrode_types["negative"] == "planar": self.reaction_loc = "interface" else: diff --git a/pybamm/models/submodels/interface/sei/no_sei.py b/pybamm/models/submodels/interface/sei/no_sei.py index 463b58bac4..590af4b376 100644 --- a/pybamm/models/submodels/interface/sei/no_sei.py +++ b/pybamm/models/submodels/interface/sei/no_sei.py @@ -21,8 +21,8 @@ class NoSEI(BaseModel): Whether this is a submodel for standard SEI or SEI on cracks """ - def __init__(self, param, options, phase="primary", cracks=False): - super().__init__(param, options=options, phase=phase, cracks=cracks) + def __init__(self, param, domain, options, phase="primary", cracks=False): + super().__init__(param, domain, options=options, phase=phase, cracks=cracks) if self.options.electrode_types[self.domain] == "planar": self.reaction_loc = "interface" else: diff --git a/pybamm/models/submodels/interface/sei/sei_growth.py b/pybamm/models/submodels/interface/sei/sei_growth.py index 08ee2f06d2..c1607d56d2 100644 --- a/pybamm/models/submodels/interface/sei/sei_growth.py +++ b/pybamm/models/submodels/interface/sei/sei_growth.py @@ -32,8 +32,10 @@ class SEIGrowth(BaseModel): Whether this is a submodel for standard SEI or SEI on cracks """ - def __init__(self, param, reaction_loc, options, phase="primary", cracks=False): - super().__init__(param, options=options, phase=phase, cracks=cracks) + def __init__( + self, param, domain, reaction_loc, options, phase="primary", cracks=False + ): + super().__init__(param, domain, options=options, phase=phase, cracks=cracks) self.reaction_loc = reaction_loc if self.options["SEI"] == "ec reaction limited": pybamm.citations.register("Yang2017") @@ -41,28 +43,28 @@ def __init__(self, param, reaction_loc, options, phase="primary", cracks=False): pybamm.citations.register("Marquis2020") def get_fundamental_variables(self): + domain, Domain = self.domain_Domain Ls = [] for pos in ["inner", "outer"]: - Pos = pos.capitalize() scale = self.phase_param.L_sei_0 if self.reaction_loc == "x-average": L_av = pybamm.Variable( - f"X-averaged {pos} {self.reaction_name}thickness [m]", + f"X-averaged {domain} {pos} {self.reaction_name}thickness [m]", domain="current collector", scale=scale, ) L_av.print_name = f"L_{pos}_av" - L = pybamm.PrimaryBroadcast(L_av, "negative electrode") + L = pybamm.PrimaryBroadcast(L_av, f"{domain} electrode") elif self.reaction_loc == "full electrode": L = pybamm.Variable( - f"{Pos} {self.reaction_name}thickness [m]", - domain="negative electrode", + f"{Domain} {pos} {self.reaction_name}thickness [m]", + domain=f"{domain} electrode", auxiliary_domains={"secondary": "current collector"}, scale=scale, ) elif self.reaction_loc == "interface": L = pybamm.Variable( - f"{Pos} {self.reaction_name}thickness [m]", + f"{Domain} {pos} {self.reaction_name}thickness [m]", domain="current collector", scale=scale, ) @@ -81,34 +83,37 @@ def get_fundamental_variables(self): def get_coupled_variables(self, variables): param = self.param phase_param = self.phase_param + domain, Domain = self.domain_Domain + T = variables[f"{Domain} electrode temperature [K]"] # delta_phi = phi_s - phi_e - T = variables["Negative electrode temperature [K]"] if self.reaction_loc == "interface": delta_phi = variables[ "Lithium metal interface surface potential difference [V]" ] T = pybamm.boundary_value(T, "right") else: - delta_phi = variables["Negative electrode surface potential difference [V]"] + delta_phi = variables[ + f"{Domain} electrode surface potential difference [V]" + ] # Look for current that contributes to the -IR drop # If we can't find the interfacial current density from the main reaction, j, # it's ok to fall back on the total interfacial current density, j_tot # This should only happen when the interface submodel is "InverseButlerVolmer" # in which case j = j_tot (uniform) anyway - if "Negative electrode interfacial current density [A.m-2]" in variables: - j = variables["Negative electrode interfacial current density [A.m-2]"] + if f"{Domain} electrode interfacial current density [A.m-2]" in variables: + j = variables[f"{Domain} electrode interfacial current density [A.m-2]"] elif self.reaction_loc == "interface": j = variables["Lithium metal total interfacial current density [A.m-2]"] else: j = variables[ - "X-averaged negative electrode total " + f"X-averaged {domain} electrode total " "interfacial current density [A.m-2]" ] - L_sei_inner = variables[f"Inner {self.reaction_name}thickness [m]"] - L_sei_outer = variables[f"Outer {self.reaction_name}thickness [m]"] - L_sei = variables[f"Total {self.reaction_name}thickness [m]"] + L_sei_inner = variables[f"{Domain} inner {self.reaction_name}thickness [m]"] + L_sei_outer = variables[f"{Domain} outer {self.reaction_name}thickness [m]"] + L_sei = variables[f"Total {domain} {self.reaction_name}thickness [m]"] R_sei = phase_param.R_sei eta_SEI = delta_phi - phase_param.U_sei - j * L_sei * R_sei @@ -162,9 +167,9 @@ def get_coupled_variables(self, variables): c_ec_av = pybamm.x_average(c_ec) if self.reaction == "SEI on cracks": - name = "EC concentration on cracks [mol.m-3]" + name = f"{Domain} EC concentration on cracks [mol.m-3]" else: - name = "EC surface concentration [mol.m-3]" + name = f"{Domain} EC surface concentration [mol.m-3]" variables.update({name: c_ec, f"X-averaged {name}": c_ec_av}) if self.options["SEI"].startswith("ec reaction limited"): @@ -189,38 +194,45 @@ def get_coupled_variables(self, variables): def set_rhs(self, variables): phase_param = self.phase_param param = self.param + domain, Domain = self.domain_Domain if self.reaction_loc == "x-average": - L_inner = variables[f"X-averaged inner {self.reaction_name}thickness [m]"] - L_outer = variables[f"X-averaged outer {self.reaction_name}thickness [m]"] + L_inner = variables[ + f"X-averaged {domain} inner {self.reaction_name}thickness [m]" + ] + L_outer = variables[ + f"X-averaged {domain} outer {self.reaction_name}thickness [m]" + ] j_inner = variables[ - f"X-averaged inner {self.reaction_name}" + f"X-averaged {domain} inner {self.reaction_name}" "interfacial current density [A.m-2]" ] j_outer = variables[ - f"X-averaged outer {self.reaction_name}" + f"X-averaged {domain} outer {self.reaction_name}" "interfacial current density [A.m-2]" ] else: - L_inner = variables[f"Inner {self.reaction_name}thickness [m]"] - L_outer = variables[f"Outer {self.reaction_name}thickness [m]"] + L_inner = variables[f"{Domain} inner {self.reaction_name}thickness [m]"] + L_outer = variables[f"{Domain} outer {self.reaction_name}thickness [m]"] j_inner = variables[ - f"Inner {self.reaction_name}interfacial current density [A.m-2]" + f"{Domain} inner {self.reaction_name}" + "interfacial current density [A.m-2]" ] j_outer = variables[ - f"Outer {self.reaction_name}interfacial current density [A.m-2]" + f"{Domain} outer {self.reaction_name}" + "interfacial current density [A.m-2]" ] # The spreading term acts to spread out SEI along the cracks as they grow. # For SEI on initial surface (as opposed to cracks), it is zero. if self.reaction == "SEI on cracks": if self.reaction_loc == "x-average": - l_cr = variables["X-averaged negative particle crack length [m]"] - dl_cr = variables["X-averaged negative particle cracking rate [m.s-1]"] + l_cr = variables[f"X-averaged {domain} particle crack length [m]"] + dl_cr = variables[f"X-averaged {domain} particle cracking rate [m.s-1]"] else: - l_cr = variables["Negative particle crack length [m]"] - dl_cr = variables["Negative particle cracking rate [m.s-1]"] + l_cr = variables[f"{Domain} particle crack length [m]"] + dl_cr = variables[f"{Domain} particle cracking rate [m.s-1]"] spreading_outer = ( dl_cr / l_cr * (self.phase_param.L_outer_crack_0 - L_outer) ) @@ -254,12 +266,17 @@ def set_rhs(self, variables): } def set_initial_conditions(self, variables): + domain, Domain = self.domain_Domain if self.reaction_loc == "x-average": - L_inner = variables[f"X-averaged inner {self.reaction_name}thickness [m]"] - L_outer = variables[f"X-averaged outer {self.reaction_name}thickness [m]"] + L_inner = variables[ + f"X-averaged {domain} inner {self.reaction_name}thickness [m]" + ] + L_outer = variables[ + f"X-averaged {domain} outer {self.reaction_name}thickness [m]" + ] else: - L_inner = variables[f"Inner {self.reaction_name}thickness [m]"] - L_outer = variables[f"Outer {self.reaction_name}thickness [m]"] + L_inner = variables[f"{Domain} inner {self.reaction_name}thickness [m]"] + L_outer = variables[f"{Domain} outer {self.reaction_name}thickness [m]"] if self.reaction == "SEI on cracks": L_inner_0 = self.phase_param.L_inner_crack_0 diff --git a/pybamm/models/submodels/interface/sei/total_sei.py b/pybamm/models/submodels/interface/sei/total_sei.py index a3ebffa6a6..2a017b94a0 100644 --- a/pybamm/models/submodels/interface/sei/total_sei.py +++ b/pybamm/models/submodels/interface/sei/total_sei.py @@ -19,24 +19,25 @@ class TotalSEI(pybamm.BaseSubModel): See :class:`pybamm.BaseBatteryModel` """ - def __init__(self, param, options, cracks=False): + def __init__(self, param, domain, options, cracks=False): if cracks is True: self.reaction = "SEI on cracks" else: self.reaction = "SEI" - super().__init__(param, options=options) + super().__init__(param, domain, options=options) def get_coupled_variables(self, variables): - phases = self.options.phases["negative"] + domain, Domain = self.domain_Domain + phases = self.options.phases[domain] # For each of the variables, the variable name without the phase name # is constructed by summing all of the variable names with the phases for variable_template in [ - f"Negative electrode {{}}{self.reaction} volumetric " + f"{Domain} electrode {{}}{self.reaction} volumetric " "interfacial current density [A.m-3]", - f"X-averaged negative electrode {{}}{self.reaction} volumetric " + f"X-averaged {domain} electrode {{}}{self.reaction} volumetric " "interfacial current density [A.m-3]", - f"Loss of lithium to {{}}{self.reaction} [mol]", - f"Loss of capacity to {{}}{self.reaction} [A.h]", + f"Loss of lithium to {domain} {{}}{self.reaction} [mol]", + f"Loss of capacity to {domain} {{}}{self.reaction} [A.h]", ]: sumvar = sum( variables[variable_template.format(phase + " ")] for phase in phases diff --git a/setup.py b/setup.py index 9eeb7b6114..6d89b34cad 100644 --- a/setup.py +++ b/setup.py @@ -250,7 +250,9 @@ def compile_KLU(): "Ai2020 = pybamm.input.parameters.lithium_ion.Ai2020:get_parameter_values", # noqa: E501 "Chen2020 = pybamm.input.parameters.lithium_ion.Chen2020:get_parameter_values", # noqa: E501 "Chen2020_composite = pybamm.input.parameters.lithium_ion.Chen2020_composite:get_parameter_values", # noqa: E501 + "Chen2020_composite_halfcell = pybamm.input.parameters.lithium_ion.Chen2020_composite_halfcell:get_parameter_values", # noqa: E501 "Ecker2015 = pybamm.input.parameters.lithium_ion.Ecker2015:get_parameter_values", # noqa: E501 + "Ecker2015_graphite_halfcell = pybamm.input.parameters.lithium_ion.Ecker2015_graphite_halfcell:get_parameter_values", # noqa: E501 "Marquis2019 = pybamm.input.parameters.lithium_ion.Marquis2019:get_parameter_values", # noqa: E501 "Mohtat2020 = pybamm.input.parameters.lithium_ion.Mohtat2020:get_parameter_values", # noqa: E501 "NCA_Kim2011 = pybamm.input.parameters.lithium_ion.NCA_Kim2011:get_parameter_values", # noqa: E501