def test_public_functions(self): param = pybamm.LithiumIonParameters() a_n = pybamm.FullBroadcast(pybamm.Scalar(0), "negative electrode", {"secondary": "current collector"}) a_p = pybamm.FullBroadcast(pybamm.Scalar(0), "positive electrode", {"secondary": "current collector"}) variables = { "Negative electrode interfacial current density": a_n, "Negative electrode temperature": a_n, "Negative electrode active material volume fraction": a_n, "Negative electrode surface area to volume ratio": a_n, "Negative particle radius": a_n, } submodel = pybamm.particle.PolynomialManyParticles( param, "Negative", "uniform profile") std_tests = tests.StandardSubModelTests(submodel, variables) std_tests.test_all() submodel = pybamm.particle.PolynomialManyParticles( param, "Negative", "quadratic profile") std_tests = tests.StandardSubModelTests(submodel, variables) std_tests.test_all() submodel = pybamm.particle.PolynomialManyParticles( param, "Negative", "quartic profile") std_tests = tests.StandardSubModelTests(submodel, variables) std_tests.test_all() variables = { "Positive electrode interfacial current density": a_p, "Positive electrode temperature": a_p, "Positive electrode active material volume fraction": a_p, "Positive electrode surface area to volume ratio": a_p, "Positive particle radius": a_p, } submodel = pybamm.particle.PolynomialManyParticles( param, "Positive", "uniform profile") std_tests = tests.StandardSubModelTests(submodel, variables) std_tests.test_all() submodel = pybamm.particle.PolynomialManyParticles( param, "Positive", "quadratic profile") std_tests = tests.StandardSubModelTests(submodel, variables) std_tests.test_all() submodel = pybamm.particle.PolynomialManyParticles( param, "Positive", "quartic profile") std_tests = tests.StandardSubModelTests(submodel, variables) std_tests.test_all()
def get_fundamental_variables(self): c_ox_av = pybamm.Variable("X-averaged oxygen concentration") c_ox_n = pybamm.FullBroadcast( c_ox_av, ["negative electrode"], "current collector" ) c_ox_s = pybamm.FullBroadcast(c_ox_av, ["separator"], "current collector") c_ox_p = pybamm.FullBroadcast( c_ox_av, ["positive electrode"], "current collector" ) c_ox = pybamm.Concatenation(c_ox_n, c_ox_s, c_ox_p) return self._get_standard_concentration_variables(c_ox)
def get_coupled_variables(self, variables): param = self.param l_n = param.l_n l_s = param.l_s l_p = param.l_p x_s = pybamm.standard_spatial_vars.x_s x_p = pybamm.standard_spatial_vars.x_p # Unpack tor_s_0_av = variables["Leading-order x-averaged separator tortuosity"] tor_p_0_av = variables[ "Leading-order x-averaged positive electrolyte tortuosity" ] # Diffusivities D_ox_s = tor_s_0_av * param.curlyD_ox D_ox_p = tor_p_0_av * param.curlyD_ox # Reactions sj_ox_p = sum( reaction["Positive"]["s_ox"] * variables[ "Leading-order x-averaged " + reaction["Positive"]["aj"].lower() ] for reaction in self.reactions.values() ) # Fluxes N_ox_n_1 = pybamm.FullBroadcast(0, "negative electrode", "current collector") N_ox_s_1 = -pybamm.PrimaryBroadcast(sj_ox_p * l_p, "separator") N_ox_p_1 = sj_ox_p * (x_p - 1) # Concentrations c_ox_n_1 = pybamm.FullBroadcast(0, "negative electrode", "current collector") c_ox_s_1 = sj_ox_p * l_p / D_ox_s * (x_s - l_n) c_ox_p_1 = ( -sj_ox_p / (2 * D_ox_p) * ((x_p - 1) ** 2 - l_p ** 2) + sj_ox_p * l_p * l_s / D_ox_s ) # Update variables c_ox = pybamm.Concatenation( param.C_e * c_ox_n_1, param.C_e * c_ox_s_1, param.C_e * c_ox_p_1 ) variables.update(self._get_standard_concentration_variables(c_ox)) N_ox = pybamm.Concatenation( param.C_e * N_ox_n_1, param.C_e * N_ox_s_1, param.C_e * N_ox_p_1 ) variables.update(self._get_standard_flux_variables(N_ox)) return variables
def test_symbol_visualise(self): param = pybamm.standard_parameters_lithium_ion one_n = pybamm.FullBroadcast(1, ["negative electrode"], "current collector") one_p = pybamm.FullBroadcast(1, ["positive electrode"], "current collector") zero_n = pybamm.FullBroadcast(0, ["negative electrode"], "current collector") zero_s = pybamm.FullBroadcast(0, ["separator"], "current collector") zero_p = pybamm.FullBroadcast(0, ["positive electrode"], "current collector") deps_dt = pybamm.Concatenation(zero_n, zero_s, zero_p) v_box = pybamm.Scalar(0) variables = { "Porosity": param.epsilon, "Porosity change": deps_dt, "Volume-averaged velocity": v_box, "Negative electrode interfacial current density": one_n, "Positive electrode interfacial current density": one_p, "Cell temperature": pybamm.Concatenation(zero_n, zero_s, zero_p), } icd = " interfacial current density" reactions = { "main": { "Negative": { "s": 1, "aj": "Negative electrode" + icd }, "Positive": { "s": 1, "aj": "Positive electrode" + icd }, } } model = pybamm.electrolyte.stefan_maxwell.diffusion.Full( param, reactions) variables.update(model.get_fundamental_variables()) variables.update(model.get_coupled_variables(variables)) model.set_rhs(variables) c_e = pybamm.standard_variables.c_e rhs = model.rhs[c_e] rhs.visualise("StefanMaxwell_test.png") self.assertTrue(os.path.exists("StefanMaxwell_test.png")) with self.assertRaises(ValueError): rhs.visualise("StefanMaxwell_test")
def test_symbol_visualise(self): param = pybamm.LithiumIonParameters() zero_n = pybamm.FullBroadcast(0, ["negative electrode"], "current collector") zero_s = pybamm.FullBroadcast(0, ["separator"], "current collector") zero_p = pybamm.FullBroadcast(0, ["positive electrode"], "current collector") zero_nsp = pybamm.concatenation(zero_n, zero_s, zero_p) v_box = pybamm.Scalar(0) variables = { "Porosity": param.epsilon, "Negative electrode porosity": param.epsilon_n, "Separator porosity": param.epsilon_s, "Positive electrode porosity": param.epsilon_p, "Electrolyte tortuosity": param.epsilon**1.5, "Porosity change": zero_nsp, "Electrolyte current density": zero_nsp, "Volume-averaged velocity": v_box, "Interfacial current density": zero_nsp, "Oxygen interfacial current density": zero_nsp, "Cell temperature": pybamm.concatenation(zero_n, zero_s, zero_p), "Transverse volume-averaged acceleration": pybamm.concatenation(zero_n, zero_s, zero_p), "Sum of electrolyte reaction source terms": zero_nsp, } model = pybamm.electrolyte_diffusion.Full(param) variables.update(model.get_fundamental_variables()) variables.update(model.get_coupled_variables(variables)) model.set_rhs(variables) rhs = list(model.rhs.values())[0] rhs.visualise("StefanMaxwell_test.png") self.assertTrue(os.path.exists("StefanMaxwell_test.png")) with self.assertRaises(ValueError): rhs.visualise("StefanMaxwell_test")
def _separator_velocity(self, variables): """ A private method to calculate x- and z-components of velocity in the separator Parameters ---------- variables : dict Dictionary of variables in the whole model. Returns ------- v_box_s : :class:`pybamm.Symbol` The x-component of velocity in the separator dVbox_dz : :class:`pybamm.Symbol` The z-component of velocity in the separator """ # Set up param = self.param l_n = pybamm.geometric_parameters.l_n l_s = pybamm.geometric_parameters.l_s x_s = pybamm.standard_spatial_vars.x_s # Difference in negative and positive electrode velocities determines the # velocity in the separator i_boundary_cc = variables["Current collector current density"] v_box_n_right = param.beta_n * i_boundary_cc v_box_p_left = param.beta_p * i_boundary_cc d_vbox_s__dx = (v_box_p_left - v_box_n_right) / l_s # Simple formula for velocity in the separator dVbox_dz = pybamm.Concatenation( pybamm.FullBroadcast( 0, "negative electrode", auxiliary_domains={"secondary": "current collector"}, ), pybamm.PrimaryBroadcast(-d_vbox_s__dx, "separator"), pybamm.FullBroadcast( 0, "positive electrode", auxiliary_domains={"secondary": "current collector"}, ), ) v_box_s = pybamm.outer(d_vbox_s__dx, (x_s - l_n)) + pybamm.PrimaryBroadcast( v_box_n_right, "separator") return v_box_s, dVbox_dz
def simplified_concatenation(*children): """ Perform simplifications on a concatenation """ # Create Concatenation to easily read domains concat = Concatenation(*children) # Simplify concatenation of broadcasts all with the same child to a single # broadcast across all domains if len(children) == 0: raise ValueError("Cannot create empty concatenation") elif len(children) == 1: return children[0] else: if all( isinstance(child, pybamm.Broadcast) and child.child.id == children[0].child.id for child in children ): unique_child = children[0].orphans[0] if isinstance(children[0], pybamm.PrimaryBroadcast): return pybamm.PrimaryBroadcast(unique_child, concat.domain) else: return pybamm.FullBroadcast( unique_child, concat.domain, concat.auxiliary_domains ) elif all(isinstance(child, pybamm.Variable) for child in children): return pybamm.ConcatenationVariable(*children) return concat
def set_rhs(self, variables): param = self.param eps = variables["Porosity"] deps_dt = variables["Porosity change"] c_e = variables["Electrolyte concentration"] N_e = variables["Electrolyte flux"] # i_e = variables["Electrolyte current density"] # source_term = ((param.s - param.t_plus) / param.gamma_e) * pybamm.div(i_e) # source_term = pybamm.div(i_e) / param.gamma_e # lithium-ion source_terms = sum( pybamm.Concatenation( reaction["Negative"]["s"] * variables[reaction["Negative"]["aj"]], pybamm.FullBroadcast(0, "separator", "current collector"), reaction["Positive"]["s"] * variables[reaction["Positive"]["aj"]], ) / param.gamma_e for reaction in self.reactions.values()) self.rhs = { c_e: (1 / eps) * (-pybamm.div(N_e) / param.C_e + source_terms - c_e * deps_dt) }
def process_dict(self, var_eqn_dict): """Discretise a dictionary of {variable: equation}, broadcasting if necessary (can be model.rhs, model.algebraic, model.initial_conditions or model.variables). Parameters ---------- var_eqn_dict : dict Equations ({variable: equation} dict) to dicretise (can be model.rhs, model.algebraic, model.initial_conditions or model.variables) Returns ------- new_var_eqn_dict : dict Discretised equations """ new_var_eqn_dict = {} for eqn_key, eqn in var_eqn_dict.items(): # Broadcast if the equation evaluates to a number(e.g. Scalar) if eqn.evaluates_to_number() and not isinstance(eqn_key, str): eqn = pybamm.FullBroadcast(eqn, eqn_key.domain, eqn_key.auxiliary_domains) # note we are sending in the key.id here so we don't have to # keep calling .id pybamm.logger.debug("Discretise {!r}".format(eqn_key)) processed_eqn = self.process_symbol(eqn) new_var_eqn_dict[eqn_key] = processed_eqn return new_var_eqn_dict
def r_average(symbol): """convenience function for creating an average in the r-direction Parameters ---------- symbol : :class:`pybamm.Symbol` The function to be averaged Returns ------- :class:`Symbol` the new averaged symbol """ # Can't take average if the symbol evaluates on edges if symbol.evaluates_on_edges("primary"): raise ValueError( "Can't take the r-average of a symbol that evaluates on edges") # If symbol doesn't have a particle domain, its r-averaged value is itself if symbol.domain not in [["positive particle"], ["negative particle"]]: new_symbol = symbol.new_copy() new_symbol.parent = None return new_symbol # If symbol is a Broadcast, its average value is its child elif isinstance(symbol, pybamm.Broadcast): return symbol.orphans[0] else: r = pybamm.SpatialVariable("r", symbol.domain) v = pybamm.FullBroadcast(pybamm.Scalar(1), symbol.domain, symbol.auxiliary_domains) return Integral(symbol, r) / Integral(v, r)
def set_rhs(self, variables): "Composite reaction-diffusion with source terms from leading order" param = self.param eps_0 = separator_and_positive_only( variables["Leading-order porosity"]) deps_0_dt = separator_and_positive_only( variables["Leading-order porosity change"]) c_ox = variables[ "Separator and positive electrode oxygen concentration"] N_ox = variables["Oxygen flux"].orphans[1] if self.extended is False: j_ox_0 = variables[ "Leading-order positive electrode oxygen interfacial current density"] pos_reactions = param.s_ox_Ox * j_ox_0 else: j_ox_0 = variables[ "Positive electrode oxygen interfacial current density"] pos_reactions = param.s_ox_Ox * j_ox_0 sep_reactions = pybamm.FullBroadcast(0, "separator", "current collector") source_terms_0 = (pybamm.Concatenation(sep_reactions, pos_reactions) / param.gamma_e) self.rhs = { c_ox: (1 / eps_0) * (-pybamm.div(N_ox) / param.C_e + source_terms_0 - c_ox * deps_0_dt) }
def get_coupled_variables(self, variables): # Simple formula for velocity in the separator v_box_s = pybamm.FullBroadcast(0, "separator", "current collector") div_v_box_s = pybamm.FullBroadcast(0, "separator", "current collector") variables.update( self._get_standard_sep_velocity_variables(v_box_s, div_v_box_s)) variables.update( self._get_standard_whole_cell_velocity_variables(variables)) variables.update( self._get_standard_whole_cell_acceleration_variables(variables)) variables.update( self._get_standard_whole_cell_pressure_variables(variables)) return variables
def set_rhs(self, variables): "Composite reaction-diffusion with source terms from leading order" param = self.param eps_0 = separator_and_positive_only(variables["Leading-order porosity"]) deps_0_dt = separator_and_positive_only( variables["Leading-order porosity change"] ) c_ox = variables["Separator and positive electrode oxygen concentration"] N_ox = variables["Oxygen flux"].orphans[1] if self.extended is False: pos_reactions = sum( reaction["Positive"]["s_ox"] * variables["Leading-order " + reaction["Positive"]["aj"].lower()] for reaction in self.reactions.values() ) else: pos_reactions = sum( reaction["Positive"]["s_ox"] * variables[reaction["Positive"]["aj"]] for reaction in self.reactions.values() ) sep_reactions = pybamm.FullBroadcast(0, "separator", "current collector") source_terms_0 = ( pybamm.Concatenation(sep_reactions, pos_reactions) / param.gamma_e ) self.rhs = { c_ox: (1 / eps_0) * (-pybamm.div(N_ox) / param.C_e + source_terms_0 - c_ox * deps_0_dt) }
def get_coupled_variables(self, variables): param = self.param if self.phase == "Electrolyte": eps_n = variables["Negative electrode porosity"] eps_s = variables["Separator porosity"] eps_p = variables["Positive electrode porosity"] tor_n = eps_n**param.b_e_n tor_s = eps_s**param.b_e_s tor_p = eps_p**param.b_e_p elif self.phase == "Electrode": eps_n = variables[ "Negative electrode active material volume fraction"] eps_p = variables[ "Positive electrode active material volume fraction"] tor_n = eps_n**param.b_e_n tor_s = pybamm.FullBroadcast(0, "separator", "current collector") tor_p = eps_p**param.b_e_p variables.update( self._get_standard_tortuosity_variables(tor_n, tor_s, tor_p, self.set_leading_order)) return variables
def get_fundamental_variables(self): zero = pybamm.FullBroadcast(pybamm.Scalar(0), self.domain.lower() + " electrode", "current collector") variables = self._get_standard_concentration_variables(zero) variables.update(self._get_standard_reaction_variables(zero)) return variables
def _get_standard_interfacial_current_variables(self, j): i_typ = self.param.i_typ L_x = self.param.L_x if self.domain == "Negative": j_scale = i_typ / (self.param.a_n_dim * L_x) elif self.domain == "Positive": j_scale = i_typ / (self.param.a_p_dim * L_x) # Average, and broadcast if necessary j_av = pybamm.x_average(j) if j.domain == []: j = pybamm.FullBroadcast(j, self.domain_for_broadcast, "current collector") elif j.domain == ["current collector"]: j = pybamm.PrimaryBroadcast(j, self.domain_for_broadcast) variables = { self.domain + " electrode" + self.reaction_name + " interfacial current density": j, "X-averaged " + self.domain.lower() + " electrode" + self.reaction_name + " interfacial current density": j_av, self.domain + " electrode" + self.reaction_name + " interfacial current density [A.m-2]": j_scale * j, "X-averaged " + self.domain.lower() + " electrode" + self.reaction_name + " interfacial current density [A.m-2]": j_scale * j_av, self.domain + " electrode" + self.reaction_name + " interfacial current density per volume [A.m-3]": i_typ / L_x * j, "X-averaged " + self.domain.lower() + " electrode" + self.reaction_name + " interfacial current density per volume [A.m-3]": i_typ / L_x * j_av, } return variables
def set_rhs(self, variables): param = self.param eps_s = variables["Separator porosity"] eps_p = variables["Positive electrode porosity"] eps = pybamm.concatenation(eps_s, eps_p) deps_dt_s = variables["Separator porosity change"] deps_dt_p = variables["Positive electrode porosity change"] deps_dt = pybamm.concatenation(deps_dt_s, deps_dt_p) c_ox = variables["Separator and positive electrode oxygen concentration"] N_ox = variables["Oxygen flux"].orphans[1] j_ox = variables["Positive electrode oxygen interfacial current density"] source_terms = pybamm.concatenation( pybamm.FullBroadcast(0, "separator", "current collector"), param.s_ox_Ox * j_ox, ) self.rhs = { c_ox: (1 / eps) * (-pybamm.div(N_ox) / param.C_e + source_terms - c_ox * deps_dt) }
def get_fundamental_variables(self): c_e_n = pybamm.FullBroadcast(1, "negative electrode", "current collector") c_e_s = pybamm.FullBroadcast(1, "separator", "current collector") c_e_p = pybamm.FullBroadcast(1, "positive electrode", "current collector") variables = self._get_standard_concentration_variables(c_e_n, c_e_s, c_e_p) N_e = pybamm.FullBroadcastToEdges( 0, ["negative electrode", "separator", "positive electrode"], "current collector", ) variables.update(self._get_standard_flux_variables(N_e)) return variables
def test_public_functions(self): param = pybamm.LithiumIonParameters() a = pybamm.Scalar(1) full = pybamm.FullBroadcast( a, ["negative electrode", "separator", "positive electrode"], "current collector", ) variables = { "Porosity": a, "Negative electrode porosity": a, "Separator porosity": a, "Positive electrode porosity": a, "Electrolyte tortuosity": a, "Porosity change": a, "Volume-averaged velocity": a, "Electrolyte concentration": a, "Electrolyte current density": full, "Sum of electrolyte reaction source terms": full, "Cell temperature": full, "Transverse volume-averaged acceleration": full, } submodel = pybamm.electrolyte_diffusion.Full(param) std_tests = tests.StandardSubModelTests(submodel, variables) std_tests.test_all()
def _get_standard_sei_film_overpotential_variables(self, eta_sei): pot_scale = self.param.potential_scale # Average, and broadcast if necessary eta_sei_av = pybamm.x_average(eta_sei) if eta_sei.domain == []: eta_sei = pybamm.FullBroadcast(eta_sei, self.domain_for_broadcast, "current collector") elif eta_sei.domain == ["current collector"]: eta_sei = pybamm.PrimaryBroadcast(eta_sei, self.domain_for_broadcast) domain = self.domain.lower() + " electrode" variables = { self.domain + " electrode sei film overpotential": eta_sei, "X-averaged " + domain + " sei film overpotential": eta_sei_av, self.domain + " electrode sei film overpotential [V]": eta_sei * pot_scale, "X-averaged " + domain + " sei film overpotential [V]": eta_sei_av * pot_scale, } return variables
def get_coupled_variables(self, variables): j_n = variables["Negative electrode interfacial current density"] j_p = variables["Positive electrode interfacial current density"] deps_n_dt = -self.param.beta_surf_n * j_n if self.options["SEI porosity change"] == "true": j_sei_n = variables[ "Negative electrode SEI interfacial current density"] beta_sei_n = self.param.beta_sei_n deps_n_dt += beta_sei_n * j_sei_n if self.options["lithium plating porosity change"] == "true": j_plating = variables[ "Negative electrode lithium plating interfacial current density"] beta_plating = self.param.beta_plating deps_n_dt += beta_plating * j_plating deps_s_dt = pybamm.FullBroadcast( 0, "separator", auxiliary_domains={"secondary": "current collector"}) deps_p_dt = -self.param.beta_surf_p * j_p variables.update( self._get_standard_porosity_change_variables( deps_n_dt, deps_s_dt, deps_p_dt)) return variables
def set_rhs(self, variables): "Composite reaction-diffusion with source terms from leading order" param = self.param eps_0 = variables["Leading-order porosity"] deps_0_dt = variables["Leading-order porosity change"] c_e = variables["Electrolyte concentration"] N_e = variables["Electrolyte flux"] if self.extended is False: sum_s_j = variables[ "Leading-order sum of electrolyte reaction source terms" ] elif self.extended == "distributed": sum_s_j = variables["Sum of electrolyte reaction source terms"] elif self.extended == "average": sum_s_j_n_av = variables[ "Sum of x-averaged negative electrode electrolyte reaction source terms" ] sum_s_j_p_av = variables[ "Sum of x-averaged positive electrode electrolyte reaction source terms" ] sum_s_j = pybamm.Concatenation( pybamm.PrimaryBroadcast(sum_s_j_n_av, "negative electrode"), pybamm.FullBroadcast(0, "separator", "current collector"), pybamm.PrimaryBroadcast(sum_s_j_p_av, "positive electrode"), ) source_terms = sum_s_j / self.param.gamma_e self.rhs = { c_e: (1 / eps_0) * (-pybamm.div(N_e) / param.C_e + source_terms - c_e * deps_0_dt) }
def get_coupled_variables(self, variables): j_n = variables[ "X-averaged negative electrode interfacial current density"] j_p = variables[ "X-averaged positive electrode interfacial current density"] j_sei_n = variables[ "X-averaged negative electrode sei interfacial current density"] beta_sei_n = self.param.beta_sei_n deps_n_dt = pybamm.PrimaryBroadcast( -self.param.beta_surf_n * j_n + beta_sei_n * j_sei_n, ["negative electrode"]) deps_s_dt = pybamm.FullBroadcast( 0, "separator", auxiliary_domains={"secondary": "current collector"}) deps_p_dt = pybamm.PrimaryBroadcast(-self.param.beta_surf_p * j_p, ["positive electrode"]) variables.update( self._get_standard_porosity_change_variables( deps_n_dt, deps_s_dt, deps_p_dt)) return variables
def test_full_broadcast(self): a = pybamm.Symbol("a") broad_a = pybamm.FullBroadcast(a, ["negative electrode"], "current collector") self.assertEqual(broad_a.domain, ["negative electrode"]) self.assertEqual(broad_a.auxiliary_domains["secondary"], ["current collector"])
def _get_standard_ocp_variables(self, ocp, dUdT): """ A private function to obtain the open circuit potential and related standard variables. Parameters ---------- ocp : :class:`pybamm.Symbol` The open-circuit potential dUdT : :class:`pybamm.Symbol` The entropic change in ocp Returns ------- variables : dict The variables dictionary including the open circuit potentials and related standard variables. """ # Average, and broadcast if necessary ocp_av = pybamm.x_average(ocp) if ocp.domain == []: ocp = pybamm.FullBroadcast( ocp, self.domain_for_broadcast, "current collector" ) elif ocp.domain == ["current collector"]: ocp = pybamm.PrimaryBroadcast(ocp, self.domain_for_broadcast) dUdT_av = pybamm.x_average(dUdT) if self.domain == "Negative": ocp_dim = self.param.U_n_ref + self.param.potential_scale * ocp ocp_av_dim = self.param.U_n_ref + self.param.potential_scale * ocp_av elif self.domain == "Positive": ocp_dim = self.param.U_p_ref + self.param.potential_scale * ocp ocp_av_dim = self.param.U_p_ref + self.param.potential_scale * ocp_av variables = { self.domain + " electrode" + self.reaction_name + " open circuit potential": ocp, self.domain + " electrode" + self.reaction_name + " open circuit potential [V]": ocp_dim, "X-averaged " + self.domain.lower() + " electrode" + self.reaction_name + " open circuit potential": ocp_av, "X-averaged " + self.domain.lower() + " electrode" + self.reaction_name + " open circuit potential [V]": ocp_av_dim, self.domain + " electrode entropic change": dUdT, "X-averaged " + self.domain.lower() + " electrode entropic change": dUdT_av, } return variables
def _get_standard_surface_potential_difference_variables(self, delta_phi): if self.domain == "Negative": ocp_ref = self.param.U_n_ref elif self.domain == "Positive": ocp_ref = self.param.U_p_ref pot_scale = self.param.potential_scale # Average, and broadcast if necessary delta_phi_av = pybamm.x_average(delta_phi) if delta_phi.domain == []: delta_phi = pybamm.FullBroadcast( delta_phi, self.domain_for_broadcast, "current collector" ) elif delta_phi.domain == ["current collector"]: delta_phi = pybamm.PrimaryBroadcast(delta_phi, self.domain_for_broadcast) variables = { self.domain + " electrode surface potential difference": delta_phi, "X-averaged " + self.domain.lower() + " electrode surface potential difference": delta_phi_av, self.domain + " electrode surface potential difference [V]": ocp_ref + delta_phi * pot_scale, "X-averaged " + self.domain.lower() + " electrode surface potential difference [V]": ocp_ref + delta_phi_av * pot_scale, } return variables
def _get_standard_overpotential_variables(self, eta_r): pot_scale = self.param.potential_scale # Average, and broadcast if necessary eta_r_av = pybamm.x_average(eta_r) if eta_r.domain == []: eta_r = pybamm.FullBroadcast( eta_r, self.domain_for_broadcast, "current collector" ) elif eta_r.domain == ["current collector"]: eta_r = pybamm.PrimaryBroadcast(eta_r, self.domain_for_broadcast) variables = { self.domain + " electrode" + self.reaction_name + " reaction overpotential": eta_r, "X-averaged " + self.domain.lower() + " electrode" + self.reaction_name + " reaction overpotential": eta_r_av, self.domain + " electrode" + self.reaction_name + " reaction overpotential [V]": eta_r * pot_scale, "X-averaged " + self.domain.lower() + " electrode" + self.reaction_name + " reaction overpotential [V]": eta_r_av * pot_scale, } return variables
def _get_standard_whole_cell_exchange_current_variables(self, variables): i_typ = self.param.i_typ L_x = self.param.L_x j_n_scale = i_typ / (self.param.a_n_dim * L_x) j_p_scale = i_typ / (self.param.a_p_dim * L_x) j0_n = variables[ "Negative electrode" + self.reaction_name + " exchange current density" ] j0_s = pybamm.FullBroadcast(0, "separator", "current collector") j0_p = variables[ "Positive electrode" + self.reaction_name + " exchange current density" ] j0 = pybamm.Concatenation(j0_n, j0_s, j0_p) j0_dim = pybamm.Concatenation(j_n_scale * j0_n, j0_s, j_p_scale * j0_p) if self.reaction_name == "": variables = { "Exchange current density": j0, "Exchange current density [A.m-2]": j0_dim, "Exchange current density per volume [A.m-3]": i_typ / L_x * j0, } else: reaction_name = self.reaction_name[1:].capitalize() variables = { reaction_name + " exchange current density": j0, reaction_name + " exchange current density [A.m-2]": j0_dim, reaction_name + " exchange current density per volume [A.m-3]": i_typ / L_x * j0, } return variables
def _flux_law(self, T): """Fast heat diffusion (temperature has no spatial dependence)""" q = pybamm.FullBroadcast( pybamm.Scalar(0), ["negative electrode", "separator", "positive electrode"], "current collector", ) return q
def epsilon_s_p(self, x): """ Positive electrode active material volume fraction, specified for compatibility with lithium-ion submodels. Note that this does not change even though porosity changes, since the material being created is inactive. """ return pybamm.FullBroadcast(1 - self.eps_p_max, "positive electrode", "current collector")