Source code for pybamm.models.submodels.interface.open_circuit_potential.base_ocp

#
# Base class for open-circuit potential
#
import pybamm
from pybamm.models.submodels.interface.base_interface import BaseInterface


[docs] class BaseOpenCircuitPotential(BaseInterface): """ Base class for open-circuit potentials Parameters ---------- param : parameter class The parameters to use for this submodel domain : str The domain to implement the model, either: 'Negative' or 'Positive'. reaction : str The name of the reaction being implemented options: dict A dictionary of options to be passed to the model. See :class:`pybamm.BaseBatteryModel` phase : str, optional Phase of the particle (default is "primary") x_average : bool Whether the particle concentration is averaged over the x-direction. Default is False. """ def __init__( self, param, domain, reaction, options, phase="primary", x_average=False ): super().__init__(param, domain, reaction, options=options, phase=phase) self.x_average = x_average def _alias_ocp_as_equilibrium(self, variables): """Publish the "equilibrium open-circuit potential [V]" variables as aliases of the main OCP variables. For OCP models without hysteresis (single OCP, MSMR) the equilibrium OCP equals the OCP, and the shapes are already handled by :meth:`_get_standard_ocp_variables`. """ domain, Domain = self.domain_Domain domain_options = getattr(self.options, domain) phase_name = self.phase_name variables.update( { f"{Domain} electrode {phase_name}equilibrium open-circuit potential [V]": variables[ f"{Domain} electrode {phase_name}open-circuit potential [V]" ], f"X-averaged {domain} electrode {phase_name}equilibrium open-circuit potential [V]": variables[ f"X-averaged {domain} electrode {phase_name}open-circuit potential [V]" ], } ) if domain_options["particle size"] == "distribution": variables.update( { f"{Domain} electrode {phase_name}equilibrium open-circuit potential distribution [V]": variables[ f"{Domain} electrode {phase_name}open-circuit potential distribution [V]" ], f"X-averaged {domain} electrode {phase_name}equilibrium open-circuit potential distribution [V]": variables[ f"X-averaged {domain} electrode {phase_name}open-circuit potential distribution [V]" ], } ) def _get_standard_ocp_variables(self, ocp_surf, ocp_bulk, dUdT): domain, Domain = self.domain_Domain reaction_name = self.reaction_name # Update size variables then size average. if ocp_surf.domain in [ ["negative particle size"], ["positive particle size"], ["negative primary particle size"], ["positive primary particle size"], ["negative secondary particle size"], ["positive secondary particle size"], ]: variables = self._get_standard_size_distribution_ocp_variables( ocp_surf, dUdT ) ocp_surf = pybamm.size_average(ocp_surf) dUdT = pybamm.size_average(dUdT) else: variables = {} # Average, and broadcast if necessary dUdT_av = pybamm.x_average(dUdT) ocp_surf_av = pybamm.x_average(ocp_surf) if self.options.electrode_types[domain] == "planar": # Half-cell domain, ocp_surf should not be broadcast pass elif ocp_surf.domain == []: ocp_surf = pybamm.FullBroadcast( ocp_surf, f"{domain} electrode", "current collector" ) elif ocp_surf.domain == ["current collector"]: ocp_surf = pybamm.PrimaryBroadcast(ocp_surf, f"{domain} electrode") # Particle overpotential is the difference between the average(U(c_surf)) and # U(c_bulk), i.e. the overpotential due to concentration gradients in the # particle eta_particle = ocp_surf_av - ocp_bulk variables.update( { f"{Domain} electrode {reaction_name}" "open-circuit potential [V]": ocp_surf, f"X-averaged {domain} electrode {reaction_name}" "open-circuit potential [V]": ocp_surf_av, f"{Domain} electrode {reaction_name}" "bulk open-circuit potential [V]": ocp_bulk, f"{Domain} {reaction_name}particle concentration " "overpotential [V]": eta_particle, } ) if self.reaction in ["lithium-ion main", "lead-acid main"]: variables.update( { f"{Domain} electrode {reaction_name}entropic change [V.K-1]": dUdT, f"X-averaged {domain} electrode {reaction_name}entropic change [V.K-1]": dUdT_av, } ) return variables def _get_standard_size_distribution_ocp_variables(self, ocp, dUdT): domain, Domain = self.domain_Domain reaction_name = self.reaction_name # X-average or broadcast to electrode if necessary if ocp.domains["secondary"] != [f"{domain} electrode"]: ocp_av = ocp ocp = pybamm.SecondaryBroadcast(ocp, f"{domain} electrode") else: ocp_av = pybamm.x_average(ocp) if dUdT.domains["secondary"] != [f"{domain} electrode"]: dUdT_av = dUdT dUdT = pybamm.SecondaryBroadcast(dUdT, f"{domain} electrode") else: dUdT_av = pybamm.x_average(dUdT) variables = { f"{Domain} electrode {reaction_name}" "open-circuit potential distribution [V]": ocp, f"X-averaged {domain} electrode {reaction_name}" "open-circuit potential distribution [V]": ocp_av, } if self.reaction_name == "": variables.update( { f"{Domain} electrode entropic change " "(size-dependent) [V.K-1]": dUdT, f"X-averaged {domain} electrode entropic change " "(size-dependent) [V.K-1]": dUdT_av, } ) return variables def _get_stoichiometry_and_temperature(self, variables): domain, Domain = self.domain_Domain domain_options = getattr(self.options, domain) phase_name = self.phase_name sto_bulk = variables[f"{Domain} electrode {phase_name}stoichiometry"] T = variables[f"{Domain} electrode temperature [K]"] T_bulk = pybamm.xyzs_average(T) # For "particle-size distribution" models, take distribution version # of sto_surf that depends on particle size. if domain_options["particle size"] == "distribution": sto_surf = variables[ f"{Domain} {phase_name}particle surface stoichiometry distribution" ] # If variable was broadcast, take only the orphan if isinstance(sto_surf, pybamm.Broadcast) and isinstance( T, pybamm.Broadcast ): sto_surf = sto_surf.orphans[0] T = T.orphans[0] T = pybamm.PrimaryBroadcast(T, [f"{domain} {phase_name}particle size"]) else: sto_surf = variables[f"{Domain} {phase_name}particle surface stoichiometry"] # If variable was broadcast, take only the orphan if isinstance(sto_surf, pybamm.Broadcast) and isinstance( T, pybamm.Broadcast ): sto_surf = sto_surf.orphans[0] T = T.orphans[0] return sto_surf, sto_bulk, T, T_bulk