Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 1575 discharge energy #1969

Merged
merged 8 commits into from
Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# [Unreleased](https://github.com/pybamm-team/PyBaMM/)

## Features

- Added "Discharge energy [W.h]", which is the integral of the power in Watts, as an optional output. Set the option "calculate discharge energy" to "true" to get this output ("false" by default, since it can slow down some of the simple models) ([#1969](https://github.com/pybamm-team/PyBaMM/pull/1969)))

## Breaking changes

- Dropped support for Windows 32-bit architecture ([#1964](https://github.com/pybamm-team/PyBaMM/pull/1964))
Expand All @@ -8,7 +12,7 @@

## Features

- Isothermal models now compute heat source terms (but the temperature remains constant). The models now also account for current collector heating when `dimensionality=0` [#1929](https://github.com/pybamm-team/PyBaMM/pull/1929))
- Isothermal models now compute heat source terms (but the temperature remains constant). The models now also account for current collector heating when `dimensionality=0` ([#1929](https://github.com/pybamm-team/PyBaMM/pull/1929)))
- Added new models for power control and resistance control ([#1917](https://github.com/pybamm-team/PyBaMM/pull/1917))
- Initial concentrations can now be provided as a function of `r` as well as `x` ([#1866](https://github.com/pybamm-team/PyBaMM/pull/1866))

Expand Down
2 changes: 1 addition & 1 deletion examples/notebooks/models/using-submodels.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@
"metadata": {},
"outputs": [],
"source": [
"model.submodels[\"external circuit\"] = pybamm.external_circuit.ExplicitCurrentControl(model.param)"
"model.submodels[\"external circuit\"] = pybamm.external_circuit.ExplicitCurrentControl(model.param, model.options)"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/custom_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

# set choice of submodels
model.submodels["external circuit"] = pybamm.external_circuit.ExplicitCurrentControl(
model.param
model.param, model.options
)
model.submodels["current collector"] = pybamm.current_collector.Uniform(model.param)
model.submodels["thermal"] = pybamm.thermal.isothermal.Isothermal(model.param)
Expand Down
35 changes: 25 additions & 10 deletions pybamm/models/full_battery_models/base_battery_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class BatteryModelOptions(pybamm.FuzzyDict):
where a 2-tuple of strings can be provided instead to indicate a different
option for the negative and positive electrodes.

* "calculate discharge energy": str
Whether to calculate the discharge energy. Must be one of "true" or
"false". "false" is the default, since calculating the discharge
energy can be computationally expensive for simple models like SPM.
* "cell geometry" : str
Sets the geometry of the cell. Can be "pouch" (default) or
"arbitrary". The arbitrary geometry option solves a 1D electrochemical
Expand Down Expand Up @@ -163,6 +167,7 @@ class BatteryModelOptions(pybamm.FuzzyDict):

def __init__(self, extra_options):
self.possible_options = {
"calculate discharge energy": ["false", "true"],
"cell geometry": ["arbitrary", "pouch"],
"convection": ["none", "uniform transverse", "full transverse"],
"current collector": [
Expand Down Expand Up @@ -916,34 +921,44 @@ def set_external_circuit_submodel(self):
e.g. (not necessarily constant-) current, voltage, etc
"""
if self.options["operating mode"] == "current":
model = pybamm.external_circuit.ExplicitCurrentControl(self.param)
model = pybamm.external_circuit.ExplicitCurrentControl(
self.param, self.options
)
elif self.options["operating mode"] == "voltage":
model = pybamm.external_circuit.VoltageFunctionControl(self.param)
model = pybamm.external_circuit.VoltageFunctionControl(
self.param, self.options
)
elif self.options["operating mode"] == "power":
model = pybamm.external_circuit.PowerFunctionControl(
self.param, "algebraic"
self.param, self.options, "algebraic"
)
elif self.options["operating mode"] == "differential power":
model = pybamm.external_circuit.PowerFunctionControl(
self.param, "differential without max"
self.param, self.options, "differential without max"
)
elif self.options["operating mode"] == "explicit power":
model = pybamm.external_circuit.ExplicitPowerControl(self.param)
model = pybamm.external_circuit.ExplicitPowerControl(
self.param, self.options
)
elif self.options["operating mode"] == "resistance":
model = pybamm.external_circuit.ResistanceFunctionControl(
self.param, "algebraic"
self.param, self.options, "algebraic"
)
elif self.options["operating mode"] == "differential resistance":
model = pybamm.external_circuit.ResistanceFunctionControl(
self.param, "differential without max"
self.param, self.options, "differential without max"
)
elif self.options["operating mode"] == "explicit resistance":
model = pybamm.external_circuit.ExplicitResistanceControl(self.param)
model = pybamm.external_circuit.ExplicitResistanceControl(
self.param, self.options
)
elif self.options["operating mode"] == "CCCV":
model = pybamm.external_circuit.CCCVFunctionControl(self.param)
model = pybamm.external_circuit.CCCVFunctionControl(
self.param, self.options
)
elif callable(self.options["operating mode"]):
model = pybamm.external_circuit.FunctionControl(
self.param, self.options["operating mode"]
self.param, self.options["operating mode"], self.options
)
self.submodels["external circuit"] = model

Expand Down
14 changes: 10 additions & 4 deletions pybamm/models/full_battery_models/lead_acid/loqs.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,26 @@ def set_external_circuit_submodel(self):
if self.options["operating mode"] == "current":
self.submodels[
"leading order external circuit"
] = pybamm.external_circuit.LeadingOrderExplicitCurrentControl(self.param)
] = pybamm.external_circuit.LeadingOrderExplicitCurrentControl(
self.param, self.options
)
elif self.options["operating mode"] == "voltage":
self.submodels[
"leading order external circuit"
] = pybamm.external_circuit.LeadingOrderVoltageFunctionControl(self.param)
] = pybamm.external_circuit.LeadingOrderVoltageFunctionControl(
self.param, self.options
)
elif self.options["operating mode"] == "power":
self.submodels[
"leading order external circuit"
] = pybamm.external_circuit.LeadingOrderPowerFunctionControl(self.param)
] = pybamm.external_circuit.LeadingOrderPowerFunctionControl(
self.param, self.options
)
elif callable(self.options["operating mode"]):
self.submodels[
"leading order external circuit"
] = pybamm.external_circuit.LeadingOrderFunctionControl(
self.param, self.options["operating mode"]
self.param, self.options["operating mode"], self.options
)

def set_current_collector_submodel(self):
Expand Down
5 changes: 3 additions & 2 deletions pybamm/models/standard_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

class StandardVariables:
def __init__(self):
# Discharge capacity
self.Q = pybamm.Variable("Discharge capacity [A.h]")
# Discharge capacity and energy
self.Q_Ah = pybamm.Variable("Discharge capacity [A.h]")
self.Q_Wh = pybamm.Variable("Discharge energy [W.h]")

# Electrolyte concentration
self.c_e_n = pybamm.Variable(
Expand Down
38 changes: 26 additions & 12 deletions pybamm/models/submodels/external_circuit/base_external_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,46 @@
class BaseModel(pybamm.BaseSubModel):
"""Model to represent the behaviour of the external circuit."""

def __init__(self, param):
super().__init__(param)
def __init__(self, param, options):
super().__init__(param, options=options)

def get_fundamental_variables(self):
Q = pybamm.standard_variables.Q
variables = {"Discharge capacity [A.h]": Q}
Q_Ah = pybamm.standard_variables.Q_Ah
variables = {"Discharge capacity [A.h]": Q_Ah}
if self.options["calculate discharge energy"] == "true":
Q_Wh = pybamm.standard_variables.Q_Wh
variables.update({"Discharge energy [W.h]": Q_Wh})
return variables

def set_initial_conditions(self, variables):
Q = variables["Discharge capacity [A.h]"]
self.initial_conditions[Q] = pybamm.Scalar(0)
Q_Ah = variables["Discharge capacity [A.h]"]
self.initial_conditions[Q_Ah] = pybamm.Scalar(0)
if self.options["calculate discharge energy"] == "true":
Q_Wh = variables["Discharge energy [W.h]"]
self.initial_conditions[Q_Wh] = pybamm.Scalar(0)

def set_rhs(self, variables):
# ODE for discharge capacity
Q = variables["Discharge capacity [A.h]"]
Q_Ah = variables["Discharge capacity [A.h]"]
I = variables["Current [A]"]
self.rhs[Q] = I * self.param.timescale / 3600

self.rhs[Q_Ah] = I * self.param.timescale / 3600
if self.options["calculate discharge energy"] == "true":
Q_Wh = variables["Discharge energy [W.h]"]
V = variables["Terminal voltage [V]"]
self.rhs[Q_Wh] = I * V * self.param.timescale / 3600


class LeadingOrderBaseModel(BaseModel):
"""Model to represent the behaviour of the external circuit, at leading order."""

def __init__(self, param):
super().__init__(param)
def __init__(self, param, options):
super().__init__(param, options)

def get_fundamental_variables(self):
Q = pybamm.Variable("Leading-order discharge capacity [A.h]")
variables = {"Discharge capacity [A.h]": Q}
Q_Ah = pybamm.Variable("Leading-order discharge capacity [A.h]")
variables = {"Discharge capacity [A.h]": Q_Ah}
if self.options["calculate discharge energy"] == "true":
Q_Wh = pybamm.Variable("Leading-order discharge energy [W.h]")
variables.update({"Discharge energy [W.h]": Q_Wh})
return variables
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
class ExplicitCurrentControl(BaseModel):
"""External circuit with current control."""

def __init__(self, param):
super().__init__(param)
def __init__(self, param, options):
super().__init__(param, options)

def get_fundamental_variables(self):
# Current is given as a function of time
Expand All @@ -34,8 +34,8 @@ def get_fundamental_variables(self):
class ExplicitPowerControl(BaseModel):
"""External circuit with current set explicitly to hit target power."""

def __init__(self, param):
super().__init__(param)
def __init__(self, param, options):
super().__init__(param, options)

def get_coupled_variables(self, variables):
param = self.param
Expand Down Expand Up @@ -64,8 +64,8 @@ def get_coupled_variables(self, variables):
class ExplicitResistanceControl(BaseModel):
"""External circuit with current set explicitly to hit target resistance."""

def __init__(self, param):
super().__init__(param)
def __init__(self, param, options):
super().__init__(param, options)

def get_coupled_variables(self, variables):
param = self.param
Expand Down Expand Up @@ -94,5 +94,5 @@ def get_coupled_variables(self, variables):
class LeadingOrderExplicitCurrentControl(ExplicitCurrentControl, LeadingOrderBaseModel):
"""External circuit with current control, for leading order models."""

def __init__(self, param):
super().__init__(param)
def __init__(self, param, options):
super().__init__(param, options)
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ class FunctionControl(BaseModel):
The parameters to use for this submodel
external_circuit_function : callable
The function that controls the current
options : dict
Dictionary of options to use for the submodel
control : str, optional
The type of control to use. Must be one of 'algebraic' (default)
or 'differential'.
"""

def __init__(self, param, external_circuit_function, control="algebraic"):
super().__init__(param)
def __init__(self, param, external_circuit_function, options, control="algebraic"):
super().__init__(param, options)
self.external_circuit_function = external_circuit_function
self.control = control

Expand Down Expand Up @@ -81,8 +83,8 @@ class VoltageFunctionControl(FunctionControl):
External circuit with voltage control, implemented as an extra algebraic equation.
"""

def __init__(self, param):
super().__init__(param, self.constant_voltage, control="algebraic")
def __init__(self, param, options):
super().__init__(param, self.constant_voltage, options, control="algebraic")

def constant_voltage(self, variables):
V = variables["Terminal voltage [V]"]
Expand All @@ -94,8 +96,8 @@ def constant_voltage(self, variables):
class PowerFunctionControl(FunctionControl):
"""External circuit with power control."""

def __init__(self, param, control):
super().__init__(param, self.constant_power, control=control)
def __init__(self, param, options, control):
super().__init__(param, self.constant_power, options, control=control)

def constant_power(self, variables):
I = variables["Current [A]"]
Expand All @@ -115,8 +117,8 @@ def constant_power(self, variables):
class ResistanceFunctionControl(FunctionControl):
"""External circuit with resistance control."""

def __init__(self, param, control):
super().__init__(param, self.constant_resistance, control=control)
def __init__(self, param, options, control):
super().__init__(param, self.constant_resistance, options, control=control)

def constant_resistance(self, variables):
I = variables["Current [A]"]
Expand Down Expand Up @@ -146,8 +148,8 @@ class CCCVFunctionControl(FunctionControl):

"""

def __init__(self, param):
super().__init__(param, self.cccv, control="differential with max")
def __init__(self, param, options):
super().__init__(param, self.cccv, options, control="differential with max")
pybamm.citations.register("Mohtat2021")

def cccv(self, variables):
Expand All @@ -165,8 +167,8 @@ def cccv(self, variables):
class LeadingOrderFunctionControl(FunctionControl, LeadingOrderBaseModel):
"""External circuit with an arbitrary function, at leading order."""

def __init__(self, param, external_circuit_class, control="algebraic"):
super().__init__(param, external_circuit_class, control=control)
def __init__(self, param, external_circuit_function, options, control="algebraic"):
super().__init__(param, external_circuit_function, options, control=control)

def _get_current_variable(self):
return pybamm.Variable("Leading-order total current density")
Expand All @@ -178,8 +180,8 @@ class LeadingOrderVoltageFunctionControl(LeadingOrderFunctionControl):
at leading order.
"""

def __init__(self, param):
super().__init__(param, self.constant_voltage, control="algebraic")
def __init__(self, param, options):
super().__init__(param, self.constant_voltage, options, control="algebraic")

def constant_voltage(self, variables):
V = variables["Terminal voltage [V]"]
Expand All @@ -191,8 +193,8 @@ def constant_voltage(self, variables):
class LeadingOrderPowerFunctionControl(LeadingOrderFunctionControl):
"""External circuit with power control, at leading order."""

def __init__(self, param):
super().__init__(param, self.constant_power, control="algebraic")
def __init__(self, param, options):
super().__init__(param, self.constant_power, options, control="algebraic")

def constant_power(self, variables):
I = variables["Current [A]"]
Expand Down
10 changes: 5 additions & 5 deletions pybamm/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def set_up_model_for_experiment_old(self, model):
# FunctionControl submodel
# create the FunctionControl submodel and extract variables
external_circuit_variables = pybamm.external_circuit.FunctionControl(
model.param, None
model.param, None, model.options
).get_fundamental_variables()

# Perform the replacement
Expand Down Expand Up @@ -396,7 +396,7 @@ def set_up_model_for_experiment_new(self, model):
# create the FunctionControl submodel and extract variables
external_circuit_variables = (
pybamm.external_circuit.FunctionControl(
model.param, None, control=control
model.param, None, model.options, control=control
).get_fundamental_variables()
)

Expand Down Expand Up @@ -470,23 +470,23 @@ def set_up_model_for_experiment_new(self, model):
new_model.algebraic[
i_cell
] = pybamm.external_circuit.VoltageFunctionControl(
new_model.param
new_model.param, model.options
).constant_voltage(
new_model.variables
)
elif op_inputs["Power switch"] == 1:
new_model.algebraic[
i_cell
] = pybamm.external_circuit.PowerFunctionControl(
new_model.param, control="algebraic"
new_model.param, new_model.options, control="algebraic"
).constant_power(
new_model.variables
)
elif op_inputs["CCCV switch"] == 1:
new_model.rhs[
i_cell
] = pybamm.external_circuit.CCCVFunctionControl(
new_model.param
new_model.param, new_model.options
).cccv(
new_model.variables
)
Expand Down
Loading