From e5e84a54bbbd48a7dec519b1bff3fc66bb30d6c7 Mon Sep 17 00:00:00 2001 From: Valentin Sulzer Date: Sun, 6 Nov 2022 17:46:36 -0500 Subject: [PATCH] #2418 fixed SPM, fixed diffusion models --- examples/scripts/compare_lithium_ion.py | 5 +- .../lithium_ion/basic_spm.py | 6 +- .../full_battery_models/lithium_ion/spme.py | 82 +++++++++---------- .../submodels/electrode/ohm/leading_ohm.py | 9 +- .../composite_conductivity.py | 3 +- .../integrated_conductivity.py | 5 +- .../leading_order_conductivity.py | 9 +- .../base_electrolyte_diffusion.py | 28 +++---- .../constant_concentration.py | 3 +- .../explicit_control_external_circuit.py | 2 +- .../submodels/interface/base_interface.py | 5 +- .../submodels/interface/sei/sei_growth.py | 8 +- .../submodels/particle/polynomial_profile.py | 9 +- pybamm/parameters/lithium_ion_parameters.py | 2 +- 14 files changed, 90 insertions(+), 86 deletions(-) diff --git a/examples/scripts/compare_lithium_ion.py b/examples/scripts/compare_lithium_ion.py index 6108036b9b..2c7d93658a 100644 --- a/examples/scripts/compare_lithium_ion.py +++ b/examples/scripts/compare_lithium_ion.py @@ -7,10 +7,11 @@ # load models models = [ + # pybamm.lithium_ion.BasicSPM(), pybamm.lithium_ion.SPM(), pybamm.lithium_ion.SPMe(), - pybamm.lithium_ion.DFN(), - pybamm.lithium_ion.NewmanTobias(), + # pybamm.lithium_ion.DFN(), + # pybamm.lithium_ion.NewmanTobias(), ] # create and run simulations diff --git a/pybamm/models/full_battery_models/lithium_ion/basic_spm.py b/pybamm/models/full_battery_models/lithium_ion/basic_spm.py index 43b7176ac4..2bd2666808 100644 --- a/pybamm/models/full_battery_models/lithium_ion/basic_spm.py +++ b/pybamm/models/full_battery_models/lithium_ion/basic_spm.py @@ -138,8 +138,8 @@ def __init__(self, name="Single Particle Model"): ###################### # Interfacial reactions RT_F = param.R * T / param.F - j0_n = param.n.prim.j0(1, c_s_surf_n, T) - j0_p = param.p.prim.j0(1, c_s_surf_p, T) + j0_n = param.n.prim.j0(param.c_e_typ, c_s_surf_n, T) + j0_p = param.p.prim.j0(param.c_e_typ, c_s_surf_p, T) eta_n = (2 / param.n.prim.ne) * RT_F * pybamm.arcsinh(j_n / (2 * j0_n)) eta_p = (2 / param.p.prim.ne) * RT_F * pybamm.arcsinh(j_p / (2 * j0_p)) phi_s_n = 0 @@ -159,7 +159,7 @@ def __init__(self, name="Single Particle Model"): c_s_surf_n, "negative electrode" ), "Electrolyte concentration [mol.m-3]": pybamm.PrimaryBroadcast( - 1, whole_cell + param.c_e_typ, whole_cell ), "Positive particle surface " "concentration [mol.m-3]": pybamm.PrimaryBroadcast( diff --git a/pybamm/models/full_battery_models/lithium_ion/spme.py b/pybamm/models/full_battery_models/lithium_ion/spme.py index 192327adbb..1db3f96395 100644 --- a/pybamm/models/full_battery_models/lithium_ion/spme.py +++ b/pybamm/models/full_battery_models/lithium_ion/spme.py @@ -67,52 +67,52 @@ def set_transport_efficiency_submodels(self): "electrode transport efficiency" ] = pybamm.transport_efficiency.Bruggeman(self.param, "Electrode", self.options) - def set_solid_submodel(self): - for domain in ["negative", "positive"]: - if self.options.electrode_types[domain] == "porous": - solid_submodel = pybamm.electrode.ohm.Composite - elif self.options.electrode_types[domain] == "planar": - if self.options["surface form"] == "false": - solid_submodel = pybamm.electrode.ohm.LithiumMetalExplicit - else: - solid_submodel = pybamm.electrode.ohm.LithiumMetalSurfaceForm - self.submodels[f"{domain} electrode potential [V]"] = solid_submodel( - self.param, domain, self.options - ) + # def set_solid_submodel(self): + # for domain in ["negative", "positive"]: + # if self.options.electrode_types[domain] == "porous": + # solid_submodel = pybamm.electrode.ohm.Composite + # elif self.options.electrode_types[domain] == "planar": + # if self.options["surface form"] == "false": + # solid_submodel = pybamm.electrode.ohm.LithiumMetalExplicit + # else: + # solid_submodel = pybamm.electrode.ohm.LithiumMetalSurfaceForm + # self.submodels[f"{domain} electrode potential [V]"] = solid_submodel( + # self.param, domain, self.options + # ) def set_electrolyte_concentration_submodel(self): self.submodels["electrolyte diffusion"] = pybamm.electrolyte_diffusion.Full( self.param, self.options ) - def set_electrolyte_potential_submodel(self): - surf_form = pybamm.electrolyte_conductivity.surface_potential_form + # def set_electrolyte_potential_submodel(self): + # surf_form = pybamm.electrolyte_conductivity.surface_potential_form - if ( - self.options["surface form"] == "false" - or self.options.electrode_types["negative"] == "planar" - ): - if self.options["electrolyte conductivity"] in ["default", "composite"]: - self.submodels[ - "electrolyte conductivity" - ] = pybamm.electrolyte_conductivity.Composite( - self.param, options=self.options - ) - elif self.options["electrolyte conductivity"] == "integrated": - self.submodels[ - "electrolyte conductivity" - ] = pybamm.electrolyte_conductivity.Integrated( - self.param, options=self.options - ) - if self.options["surface form"] == "false": - surf_model = surf_form.Explicit - elif self.options["surface form"] == "differential": - surf_model = surf_form.CompositeDifferential - elif self.options["surface form"] == "algebraic": - surf_model = surf_form.CompositeAlgebraic + # if ( + # self.options["surface form"] == "false" + # or self.options.electrode_types["negative"] == "planar" + # ): + # if self.options["electrolyte conductivity"] in ["default", "composite"]: + # self.submodels[ + # "electrolyte conductivity" + # ] = pybamm.electrolyte_conductivity.Composite( + # self.param, options=self.options + # ) + # elif self.options["electrolyte conductivity"] == "integrated": + # self.submodels[ + # "electrolyte conductivity" + # ] = pybamm.electrolyte_conductivity.Integrated( + # self.param, options=self.options + # ) + # if self.options["surface form"] == "false": + # surf_model = surf_form.Explicit + # elif self.options["surface form"] == "differential": + # surf_model = surf_form.CompositeDifferential + # elif self.options["surface form"] == "algebraic": + # surf_model = surf_form.CompositeAlgebraic - for domain in ["negative", "positive"]: - if self.options.electrode_types[domain] == "porous": - self.submodels[ - f"{domain} surface potential difference [V]" - ] = surf_model(self.param, domain, self.options) + # for domain in ["negative", "positive"]: + # if self.options.electrode_types[domain] == "porous": + # self.submodels[ + # f"{domain} surface potential difference [V]" + # ] = surf_model(self.param, domain, self.options) diff --git a/pybamm/models/submodels/electrode/ohm/leading_ohm.py b/pybamm/models/submodels/electrode/ohm/leading_ohm.py index 94ec9eb6ae..248a89f05a 100644 --- a/pybamm/models/submodels/electrode/ohm/leading_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/leading_ohm.py @@ -43,14 +43,15 @@ def get_coupled_variables(self, variables): phi_s_cn = variables["Negative current collector potential [V]"] # import parameters and spatial variables - l_n = param.n.L - l_p = param.p.L + L_n = param.n.L + L_p = param.p.L + L_x = param.L_x x_n = pybamm.standard_spatial_vars.x_n x_p = pybamm.standard_spatial_vars.x_p if self.domain == "negative": phi_s = pybamm.PrimaryBroadcast(phi_s_cn, "negative electrode") - i_s = i_boundary_cc * (1 - x_n / l_n) + i_s = i_boundary_cc * (1 - x_n / L_n) elif self.domain == "positive": # recall delta_phi = phi_s - phi_e @@ -62,7 +63,7 @@ def get_coupled_variables(self, variables): v = delta_phi_p_av + phi_e_p_av phi_s = pybamm.PrimaryBroadcast(v, ["positive electrode"]) - i_s = i_boundary_cc * (1 - (1 - x_p) / l_p) + i_s = i_boundary_cc * (1 - (L_x - x_p) / L_p) variables.update(self._get_standard_potential_variables(phi_s)) variables.update(self._get_standard_current_variables(i_s)) diff --git a/pybamm/models/submodels/electrolyte_conductivity/composite_conductivity.py b/pybamm/models/submodels/electrolyte_conductivity/composite_conductivity.py index f1ab1b355c..076090939d 100644 --- a/pybamm/models/submodels/electrolyte_conductivity/composite_conductivity.py +++ b/pybamm/models/submodels/electrolyte_conductivity/composite_conductivity.py @@ -62,6 +62,7 @@ def get_coupled_variables(self, variables): L_n = param.n.L L_s = param.s.L L_p = param.p.L + L_x = param.L_x x_s = pybamm.standard_spatial_vars.x_s x_p = pybamm.standard_spatial_vars.x_p @@ -84,7 +85,7 @@ def get_coupled_variables(self, variables): kappa_n_av = param.kappa_e(c_e_av, T_av) * tor_n_av i_e_n = i_boundary_cc * x_n / L_n i_e_s = pybamm.PrimaryBroadcast(i_boundary_cc, "separator") - i_e_p = i_boundary_cc * (1 - x_p) / L_p + i_e_p = i_boundary_cc * (L_x - x_p) / L_p i_e = pybamm.concatenation(i_e_n, i_e_s, i_e_p) phi_e_dict = {} diff --git a/pybamm/models/submodels/electrolyte_conductivity/integrated_conductivity.py b/pybamm/models/submodels/electrolyte_conductivity/integrated_conductivity.py index 2ecd8737b0..62ecaad605 100644 --- a/pybamm/models/submodels/electrolyte_conductivity/integrated_conductivity.py +++ b/pybamm/models/submodels/electrolyte_conductivity/integrated_conductivity.py @@ -70,6 +70,7 @@ def get_coupled_variables(self, variables): param = self.param L_n = param.n.L L_p = param.p.L + L_x = param.L_x x_n = pybamm.standard_spatial_vars.x_n x_s = pybamm.standard_spatial_vars.x_s x_p = pybamm.standard_spatial_vars.x_p @@ -84,12 +85,12 @@ def get_coupled_variables(self, variables): # electrolyte current i_e_n = i_boundary_cc * x_n / L_n i_e_s = pybamm.PrimaryBroadcast(i_boundary_cc, "separator") - i_e_p = i_boundary_cc * (1 - x_p) / L_p + i_e_p = i_boundary_cc * (L_x - x_p) / L_p i_e = pybamm.concatenation(i_e_n, i_e_s, i_e_p) i_e_n_edge = i_boundary_cc * x_n_edge / L_n i_e_s_edge = pybamm.PrimaryBroadcastToEdges(i_boundary_cc, "separator") - i_e_p_edge = i_boundary_cc * (1 - x_p_edge) / L_p + i_e_p_edge = i_boundary_cc * (L_x - x_p_edge) / L_p # electrolyte potential indef_integral_n = pybamm.IndefiniteIntegral( diff --git a/pybamm/models/submodels/electrolyte_conductivity/leading_order_conductivity.py b/pybamm/models/submodels/electrolyte_conductivity/leading_order_conductivity.py index c0a46ecf32..9893b2a0ac 100644 --- a/pybamm/models/submodels/electrolyte_conductivity/leading_order_conductivity.py +++ b/pybamm/models/submodels/electrolyte_conductivity/leading_order_conductivity.py @@ -39,15 +39,16 @@ def get_coupled_variables(self, variables): i_boundary_cc = variables["Current collector current density [A.m-2]"] param = self.param - l_n = param.n.L - l_p = param.p.L + L_n = param.n.L + L_p = param.p.L + L_x = param.L_x x_n = pybamm.standard_spatial_vars.x_n x_p = pybamm.standard_spatial_vars.x_p if "negative electrode" not in self.options.whole_cell_domains: i_e_n = None else: - i_e_n = i_boundary_cc * x_n / l_n + i_e_n = i_boundary_cc * x_n / L_n phi_e_dict = { domain: pybamm.PrimaryBroadcast(phi_e_av, domain) @@ -55,7 +56,7 @@ def get_coupled_variables(self, variables): } i_e_s = pybamm.PrimaryBroadcast(i_boundary_cc, ["separator"]) - i_e_p = i_boundary_cc * (1 - x_p) / l_p + i_e_p = i_boundary_cc * (L_x - x_p) / L_p i_e = pybamm.concatenation(i_e_n, i_e_s, i_e_p) variables.update(self._get_standard_potential_variables(phi_e_dict)) diff --git a/pybamm/models/submodels/electrolyte_diffusion/base_electrolyte_diffusion.py b/pybamm/models/submodels/electrolyte_diffusion/base_electrolyte_diffusion.py index c50f564351..6e71857a3b 100644 --- a/pybamm/models/submodels/electrolyte_diffusion/base_electrolyte_diffusion.py +++ b/pybamm/models/submodels/electrolyte_diffusion/base_electrolyte_diffusion.py @@ -37,14 +37,13 @@ def _get_standard_concentration_variables(self, c_e_dict): electrolyte. """ - c_e_typ = self.param.c_e_typ c_e = pybamm.concatenation(*c_e_dict.values()) # Override print_name c_e.print_name = "c_e" variables = { - "Electrolyte concentration": c_e, - "X-averaged electrolyte concentration": pybamm.x_average(c_e), + "Electrolyte concentration [mol.m-3]": c_e, + "X-averaged electrolyte concentration [mol.m-3]": pybamm.x_average(c_e), } # Case where an electrode is not included (half-cell) @@ -58,18 +57,20 @@ def _get_standard_concentration_variables(self, c_e_dict): c_e_k_av = pybamm.x_average(c_e_k) variables.update( { - f"{Domain} electrolyte concentration": c_e_k, - f"X-averaged {domain} electrolyte concentration": c_e_k_av, + f"{Domain} electrolyte concentration [mol.m-3]": c_e_k, + f"X-averaged {domain} electrolyte " + "concentration [mol.m-3]": c_e_k_av, } ) - # Calculate dimensional variables - variables_nondim = variables.copy() - for name, var in variables_nondim.items(): + # Calculate dimensionless and molar variables + variables_dim = variables.copy() + for name, var in variables_dim.items(): + name = name.replace(" [mol.m-3]", "") variables.update( { - f"{name} [mol.m-3]": c_e_typ * var, - f"{name} [Molar]": c_e_typ * var / 1000, + name: var / self.param.c_e_typ, + f"{name} [Molar]": var / 1000, } ) @@ -119,16 +120,11 @@ def _get_total_concentration_electrolyte(self, eps_c_e): variables : dict The "Total lithium in electrolyte [mol]" variable. """ - - c_e_typ = self.param.c_e_typ L_x = self.param.L_x A = self.param.A_cc eps_c_e_av = pybamm.yz_average(pybamm.x_average(eps_c_e)) - variables = { - "Total lithium in electrolyte": eps_c_e_av, - "Total lithium in electrolyte [mol]": c_e_typ * L_x * A * eps_c_e_av, - } + variables = {"Total lithium in electrolyte [mol]": L_x * A * eps_c_e_av} return variables diff --git a/pybamm/models/submodels/electrolyte_diffusion/constant_concentration.py b/pybamm/models/submodels/electrolyte_diffusion/constant_concentration.py index 8da3517e3c..12eafbd9c8 100644 --- a/pybamm/models/submodels/electrolyte_diffusion/constant_concentration.py +++ b/pybamm/models/submodels/electrolyte_diffusion/constant_concentration.py @@ -23,8 +23,9 @@ def __init__(self, param, options=None): super().__init__(param, options) def get_fundamental_variables(self): + c_e_init = self.param.c_e_init c_e_dict = { - domain: pybamm.FullBroadcast(1, domain, "current collector") + domain: pybamm.FullBroadcast(c_e_init, domain, "current collector") for domain in self.options.whole_cell_domains } variables = self._get_standard_concentration_variables(c_e_dict) diff --git a/pybamm/models/submodels/external_circuit/explicit_control_external_circuit.py b/pybamm/models/submodels/external_circuit/explicit_control_external_circuit.py index e14625f65c..4f6c918893 100644 --- a/pybamm/models/submodels/external_circuit/explicit_control_external_circuit.py +++ b/pybamm/models/submodels/external_circuit/explicit_control_external_circuit.py @@ -17,7 +17,7 @@ def get_fundamental_variables(self): I = self.param.current_with_time variables = { - "Current density variable": pybamm.Scalar(1, name="i_cell"), + "Current density variable [A.m-2]": i_cell, "Total current density [A.m-2]": i_cell, "Current [A]": I, "C-rate": I / self.param.Q, diff --git a/pybamm/models/submodels/interface/base_interface.py b/pybamm/models/submodels/interface/base_interface.py index c1e86514df..d9bd68a542 100644 --- a/pybamm/models/submodels/interface/base_interface.py +++ b/pybamm/models/submodels/interface/base_interface.py @@ -75,7 +75,8 @@ def _get_exchange_current_density(self, variables): # of c_s_surf that depends on particle size. if self.options["particle size"] == "distribution": c_s_surf = variables[ - f"{Domain} {phase_name}particle surface concentration distribution" + f"{Domain} {phase_name}particle surface " + "concentration distribution [mol.m-3]" ] # If all variables were broadcast (in "x"), take only the orphans, # then re-broadcast c_e @@ -97,7 +98,7 @@ def _get_exchange_current_density(self, variables): else: c_s_surf = variables[ - f"{Domain} {phase_name}particle surface concentration" + f"{Domain} {phase_name}particle surface concentration [mol.m-3]" ] # If all variables were broadcast, take only the orphans if ( diff --git a/pybamm/models/submodels/interface/sei/sei_growth.py b/pybamm/models/submodels/interface/sei/sei_growth.py index ab3811de16..fdb21ef994 100644 --- a/pybamm/models/submodels/interface/sei/sei_growth.py +++ b/pybamm/models/submodels/interface/sei/sei_growth.py @@ -160,12 +160,10 @@ 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" + name = "EC concentration on cracks [mol.m-3]" else: - name = "EC surface concentration" - variables.update( - {f"{name} [mol.m-3]": c_ec, f"X-averaged {name} [mol.m-3]": c_ec_av} - ) + name = "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"): inner_sei_proportion = 0 diff --git a/pybamm/models/submodels/particle/polynomial_profile.py b/pybamm/models/submodels/particle/polynomial_profile.py index ff5121f5bb..14a266c692 100644 --- a/pybamm/models/submodels/particle/polynomial_profile.py +++ b/pybamm/models/submodels/particle/polynomial_profile.py @@ -100,7 +100,7 @@ def get_fundamental_variables(self): # We solve an equation for the surface concentration, so it is # a variable in the model c_s_surf = pybamm.Variable( - f"{Domain} particle surface concentration", + f"{Domain} particle surface concentration [mol.m-3]", domain=f"{domain} electrode", auxiliary_domains={"secondary": "current collector"}, bounds=(0, 1), @@ -112,12 +112,15 @@ def get_fundamental_variables(self): # distinction between the flux defined as N = -D*dc/dr and the # concentration gradient q = dc/dr q_s_rav = pybamm.Variable( - f"R-averaged {domain} particle concentration gradient", + f"R-averaged {domain} particle concentration gradient [mol.m-4]", domain=f"{domain} electrode", auxiliary_domains={"secondary": "current collector"}, ) variables.update( - {f"R-averaged {domain} particle concentration gradient": q_s_rav} + { + f"R-averaged {domain} particle " + "concentration gradient [mol.m-4]": q_s_rav + } ) # Set concentration depending on polynomial order diff --git a/pybamm/parameters/lithium_ion_parameters.py b/pybamm/parameters/lithium_ion_parameters.py index fcb29c933a..f16b2beaca 100644 --- a/pybamm/parameters/lithium_ion_parameters.py +++ b/pybamm/parameters/lithium_ion_parameters.py @@ -127,7 +127,7 @@ def _set_parameters(self): # Total lithium # Electrolyte - c_e_av_init = pybamm.xyz_average(self.epsilon_init) * self.c_e_typ + c_e_av_init = pybamm.xyz_average(self.epsilon_init) * self.c_e_init self.n_Li_e_init = c_e_av_init * self.L_x * self.A_cc self.n_Li_particles_init = self.n.n_Li_init + self.p.n_Li_init