Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
22 changes: 11 additions & 11 deletions src/pathsim_batt/cells/pybamm_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ class CellElectrical(_CellBase):
"""Cell block — electrical outputs only, external thermal coupling.

PathSim integrates both the electrochemical state (via the discretised
PyBaMM ODE) and the cell temperature ODE. Wire ``Q_heat`` to a
PyBaMM ODE) and the cell temperature ODE. Wire ``Q_dot`` to a
``LumpedThermal`` (or similar) block and feed its temperature output
back to ``T_cell``.

Expand Down Expand Up @@ -302,19 +302,19 @@ class CellElectrical(_CellBase):
Outputs
-------
V (0) : terminal voltage [V]
Q_heat (1) : X-averaged volumetric heat generation [W m⁻³]
Q_dot (1) : total heat generation [W]
SOC (2) : state of charge (0–1)
"""

_thermal_option = "isothermal"
_thermal_extra_options = {"calculate heat source for isothermal models": "true"}
_pybamm_output_vars = [
"Terminal voltage [V]",
"X-averaged total heating [W.m-3]",
"Total heating [W]",
]

input_port_labels = {"I": 0, "T_cell": 1}
output_port_labels = {"V": 0, "Q_heat": 1, "SOC": 2}
output_port_labels = {"V": 0, "Q_dot": 1, "SOC": 2}


class CellElectrothermal(_CellBase):
Expand Down Expand Up @@ -352,19 +352,19 @@ class CellElectrothermal(_CellBase):
-------
V (0) : terminal voltage [V]
T (1) : cell temperature [K] (part of PyBaMM state)
Q_heat (2) : X-averaged volumetric heat generation [W m⁻³]
Q_dot (2) : total heat generation [W]
SOC (3) : state of charge (0–1)
"""

_thermal_option = "lumped"
_pybamm_output_vars = [
"Terminal voltage [V]",
"X-averaged cell temperature [K]",
"X-averaged total heating [W.m-3]",
"Total heating [W]",
]

input_port_labels = {"I": 0, "T_amb": 1}
output_port_labels = {"V": 0, "T": 1, "Q_heat": 2, "SOC": 3}
output_port_labels = {"V": 0, "T": 1, "Q_dot": 2, "SOC": 3}


class CellCoSimElectrical(_CoSimCellBase):
Expand Down Expand Up @@ -396,11 +396,11 @@ class CellCoSimElectrical(_CoSimCellBase):
_thermal_extra_options = {"calculate heat source for isothermal models": "true"}
_pybamm_output_vars = [
"Terminal voltage [V]",
"X-averaged total heating [W.m-3]",
"Total heating [W]",
]

input_port_labels = {"I": 0, "T_cell": 1}
output_port_labels = {"V": 0, "Q_heat": 1, "SOC": 2}
output_port_labels = {"V": 0, "Q_dot": 1, "SOC": 2}


class CellCoSimElectrothermal(_CoSimCellBase):
Expand Down Expand Up @@ -431,8 +431,8 @@ class CellCoSimElectrothermal(_CoSimCellBase):
_pybamm_output_vars = [
"Terminal voltage [V]",
"X-averaged cell temperature [K]",
"X-averaged total heating [W.m-3]",
"Total heating [W]",
]

input_port_labels = {"I": 0, "T_amb": 1}
output_port_labels = {"V": 0, "T": 1, "Q_heat": 2, "SOC": 3}
output_port_labels = {"V": 0, "T": 1, "Q_dot": 2, "SOC": 3}
38 changes: 19 additions & 19 deletions tests/cells/test_pybamm_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def test_electrical_input_labels(self):

def test_electrical_output_labels(self):
self.assertEqual(CellElectrical.output_port_labels["V"], 0)
self.assertEqual(CellElectrical.output_port_labels["Q_heat"], 1)
self.assertEqual(CellElectrical.output_port_labels["Q_dot"], 1)
self.assertEqual(CellElectrical.output_port_labels["SOC"], 2)

def test_electrothermal_input_labels(self):
Expand All @@ -31,7 +31,7 @@ def test_electrothermal_input_labels(self):
def test_electrothermal_output_labels(self):
self.assertEqual(CellElectrothermal.output_port_labels["V"], 0)
self.assertEqual(CellElectrothermal.output_port_labels["T"], 1)
self.assertEqual(CellElectrothermal.output_port_labels["Q_heat"], 2)
self.assertEqual(CellElectrothermal.output_port_labels["Q_dot"], 2)
self.assertEqual(CellElectrothermal.output_port_labels["SOC"], 3)

def test_is_dynamic(self):
Expand All @@ -40,17 +40,17 @@ def test_is_dynamic(self):

def test_cosim_len_zero(self):
cell_e = CellCoSimElectrical(dt=1.0)
self.assertEqual(len(cell_e), 3) # V, Q_heat, SOC
self.assertEqual(len(cell_e), 3) # V, Q_dot, SOC
cell_et = CellCoSimElectrothermal(dt=1.0)
self.assertEqual(len(cell_et), 4) # V, T, Q_heat, SOC
self.assertEqual(len(cell_et), 4) # V, T, Q_dot, SOC

def test_len_zero(self):
cell_e = CellElectrical()
cell_e.set_solver(ESDIRK43, None)
self.assertEqual(len(cell_e), 3) # V, Q_heat, SOC
self.assertEqual(len(cell_e), 3) # V, Q_dot, SOC
cell_et = CellElectrothermal()
cell_et.set_solver(ESDIRK43, None)
self.assertEqual(len(cell_et), 4) # V, T, Q_heat, SOC
self.assertEqual(len(cell_et), 4) # V, T, Q_dot, SOC

def test_current_always_input(self):
pv = pybamm.ParameterValues("Chen2020")
Expand Down Expand Up @@ -168,7 +168,7 @@ def test_outputs_in_range(self):
self.sim.run(1)
self.assertGreater(self.cell.outputs[0], 3.0) # V
self.assertLess(self.cell.outputs[0], 4.3)
self.assertGreaterEqual(self.cell.outputs[1], 0.0) # Q_heat
self.assertGreaterEqual(self.cell.outputs[1], 0.0) # Q_dot
self.assertGreater(self.cell.outputs[2], 0.0) # SOC
self.assertLessEqual(self.cell.outputs[2], 1.0)

Expand All @@ -191,10 +191,10 @@ def test_pathsim_state_advances(self):
self.assertFalse(np.allclose(self.cell.engine.state, state_before))

def test_q_heat_nonzero_during_discharge(self):
"""Q_heat must be strictly positive when a discharge current flows.
"""Q_dot must be strictly positive when a discharge current flows.

With thermal='isothermal' PyBaMM does not compute heat source terms,
so Q_heat would be identically zero — this test guards against that.
so Q_dot would be identically zero — this test guards against that.
"""
cell = CellElectrical(initial_soc=1.0)
I_src = Constant(5.0) # 1C-ish discharge
Expand All @@ -212,7 +212,7 @@ def test_q_heat_nonzero_during_discharge(self):
self.assertGreater(
cell.outputs[1],
0.0,
"Q_heat is zero — thermal model may not compute heat sources",
"Q_dot is zero — thermal model may not compute heat sources",
)

def test_temperature_input_affects_voltage(self):
Expand Down Expand Up @@ -276,7 +276,7 @@ def test_outputs_in_range(self):
self.assertLess(self.cell.outputs[0], 4.3)
self.assertGreater(self.cell.outputs[1], 250.0) # T
self.assertLess(self.cell.outputs[1], 400.0)
self.assertGreaterEqual(self.cell.outputs[2], 0.0) # Q_heat
self.assertGreaterEqual(self.cell.outputs[2], 0.0) # Q_dot
self.assertGreater(self.cell.outputs[3], 0.0) # SOC
self.assertLessEqual(self.cell.outputs[3], 1.0)

Expand All @@ -299,7 +299,7 @@ def test_pathsim_state_advances(self):
self.assertFalse(np.allclose(self.cell.engine.state, state_before))

def test_q_heat_nonzero_during_discharge(self):
"""Q_heat must be strictly positive when a discharge current flows."""
"""Q_dot must be strictly positive when a discharge current flows."""
cell = CellElectrothermal(initial_soc=1.0)
I_src = Constant(5.0)
T_src = Constant(298.15)
Expand All @@ -316,7 +316,7 @@ def test_q_heat_nonzero_during_discharge(self):
self.assertGreater(
cell.outputs[2],
0.0,
"Q_heat is zero — thermal model may not compute heat sources",
"Q_dot is zero — thermal model may not compute heat sources",
)

def test_tamb_input_affects_cell_temperature(self):
Expand Down Expand Up @@ -375,7 +375,7 @@ def test_outputs_in_range(self):
self.sim.run(2)
self.assertGreater(self.cell.outputs[0], 2.0) # V
self.assertLess(self.cell.outputs[0], 5.0)
self.assertGreaterEqual(self.cell.outputs[1], 0.0) # Q_heat
self.assertGreaterEqual(self.cell.outputs[1], 0.0) # Q_dot
self.assertGreater(self.cell.outputs[2], 0.0) # SOC
self.assertLessEqual(self.cell.outputs[2], 1.0)

Expand Down Expand Up @@ -404,7 +404,7 @@ def test_dfn_step_outputs_physical(self):
self.assertLessEqual(cell.outputs[2], 1.0)

def test_q_heat_nonzero_during_discharge(self):
"""Q_heat must be strictly positive when a discharge current flows."""
"""Q_dot must be strictly positive when a discharge current flows."""
cell = CellCoSimElectrical(initial_soc=1.0, dt=10.0)
I_src = Constant(5.0)
T_src = Constant(298.15)
Expand All @@ -421,7 +421,7 @@ def test_q_heat_nonzero_during_discharge(self):
self.assertGreater(
cell.outputs[1],
0.0,
"Q_heat is zero — thermal model may not compute heat sources",
"Q_dot is zero — thermal model may not compute heat sources",
)

def test_temperature_input_affects_voltage(self):
Expand Down Expand Up @@ -479,7 +479,7 @@ def test_outputs_in_range(self):
self.assertLess(self.cell.outputs[0], 5.0)
self.assertGreater(self.cell.outputs[1], 250.0) # T
self.assertLess(self.cell.outputs[1], 400.0)
self.assertGreaterEqual(self.cell.outputs[2], 0.0) # Q_heat
self.assertGreaterEqual(self.cell.outputs[2], 0.0) # Q_dot
self.assertGreater(self.cell.outputs[3], 0.0) # SOC
self.assertLessEqual(self.cell.outputs[3], 1.0)

Expand Down Expand Up @@ -509,7 +509,7 @@ def test_dfn_step_outputs_physical(self):
self.assertLessEqual(cell.outputs[3], 1.0)

def test_q_heat_nonzero_during_discharge(self):
"""Q_heat must be strictly positive when a discharge current flows."""
"""Q_dot must be strictly positive when a discharge current flows."""
cell = CellCoSimElectrothermal(initial_soc=1.0, dt=10.0)
I_src = Constant(5.0)
T_src = Constant(298.15)
Expand All @@ -526,7 +526,7 @@ def test_q_heat_nonzero_during_discharge(self):
self.assertGreater(
cell.outputs[2],
0.0,
"Q_heat is zero — thermal model may not compute heat sources",
"Q_dot is zero — thermal model may not compute heat sources",
)

def test_tamb_input_affects_cell_temperature(self):
Expand Down
Loading