mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-10-21 05:11:57 +00:00
fix(devices): let EVs finish charging within the final slot (#1423)
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
from akkudoktoreos.devices.genetic.battery import (
|
||||
Battery,
|
||||
ElectricVehicleParameters,
|
||||
SolarPanelBatteryParameters,
|
||||
)
|
||||
|
||||
RATES = [0.0] + [amps / 16 for amps in range(6, 17)]
|
||||
|
||||
|
||||
def battery(kind=ElectricVehicleParameters, soc=99, maximum=100):
|
||||
parameters = kind(
|
||||
device_id="ev-test", capacity_wh=60000,
|
||||
initial_soc_percentage=int(soc), charging_efficiency=0.95,
|
||||
discharging_efficiency=1.0, max_charge_power_w=11040,
|
||||
max_soc_percentage=maximum, charge_rates=RATES,
|
||||
)
|
||||
value = Battery(parameters, prediction_hours=4, slot_duration_h=0.25)
|
||||
value.reset()
|
||||
value.soc_wh = soc / 100 * value.capacity_wh
|
||||
value.charge_array = np.full(4, 0.375)
|
||||
return value
|
||||
|
||||
|
||||
class TestEVMinimumCurrent(unittest.TestCase):
|
||||
def test_ev_finishes_within_final_slot_at_unchanged_minimum_current(self):
|
||||
for soc in [98.5, 99.0, 99.9]:
|
||||
with self.subTest(soc=soc):
|
||||
value = battery(soc=soc)
|
||||
missing = 60000 - value.soc_wh
|
||||
stored, losses = value.charge_energy(None, 0, charge_factor=0.375)
|
||||
self.assertAlmostEqual(stored, missing)
|
||||
self.assertAlmostEqual(value.soc_wh, 60000)
|
||||
self.assertAlmostEqual(losses, missing / 0.95 - missing)
|
||||
self.assertEqual(value.charge_array[0], 0.375)
|
||||
self.assertLessEqual(stored + losses, 4140 * 0.25)
|
||||
|
||||
def test_full_ev_has_no_charge_command_or_energy(self):
|
||||
value = battery(soc=100)
|
||||
self.assertEqual(value.charge_energy(None, 0, charge_factor=0.375), (0.0, 0.0))
|
||||
self.assertEqual(value.charge_array[0], 0)
|
||||
|
||||
def test_complete_minimum_current_slot_preserves_watt_hours(self):
|
||||
value = battery(soc=80)
|
||||
stored, losses = value.charge_energy(None, 0, charge_factor=0.375)
|
||||
self.assertAlmostEqual(stored + losses, 4140 * 0.25)
|
||||
self.assertAlmostEqual(stored, 4140 * 0.25 * 0.95)
|
||||
|
||||
def test_ev_respects_a_lower_configured_maximum(self):
|
||||
value = battery(soc=95.9, maximum=96)
|
||||
value.charge_energy(None, 0, charge_factor=0.375)
|
||||
self.assertAlmostEqual(value.soc_wh, 60000 * 0.96)
|
||||
|
||||
def test_stationary_battery_keeps_discrete_rate_behavior(self):
|
||||
value = battery(SolarPanelBatteryParameters, soc=99)
|
||||
self.assertEqual(value.charge_energy(None, 0, charge_factor=0.375), (0.0, 0.0))
|
||||
self.assertEqual(value.soc_wh, 59400)
|
||||
self.assertEqual(value.charge_array[0], 0)
|
||||
|
||||
def test_final_slot_preserves_each_configured_current(self):
|
||||
for amps in range(6, 17):
|
||||
with self.subTest(amps=amps):
|
||||
value = battery(soc=99.9)
|
||||
factor = amps / 16
|
||||
value.charge_array[0] = factor
|
||||
missing = value.max_soc_wh - value.soc_wh
|
||||
stored, losses = value.charge_energy(None, 0, charge_factor=factor)
|
||||
self.assertAlmostEqual(stored, missing)
|
||||
self.assertAlmostEqual(value.soc_wh, value.max_soc_wh)
|
||||
self.assertAlmostEqual(losses, missing / 0.95 - missing)
|
||||
self.assertEqual(value.charge_array[0], factor)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user