Spaces:
Sleeping
Sleeping
| from dataclasses import dataclass | |
| class BatteryParameters: | |
| capacity_Ah: float = 330 | |
| efficiency: float = 0.9 # [dimensionless] | |
| voltage_V: float = 600 | |
| charge_kW: float = 50 | |
| discharge_kW: float = 60 | |
| # SOC is normalized so that minimal_depth_of_discharge = 0 and maximal_depth_of_discharge = 1. | |
| # please set capacity_Ah = nominal_capacity_Ah * (max_dod - min_dod) | |
| # | |
| # TODO efficiency multiplier is not currently used, where best to put it? | |
| class BatteryModel: | |
| def __init__(self, battery_parameters, time_interval_h): | |
| self.p = battery_parameters | |
| self.time_interval_h = time_interval_h | |
| # the only non-constant member variable! | |
| # ratio of self.current_capacity_kWh and self.maximal_capacity_kWh | |
| self.soc = 0.0 | |
| def maximal_capacity_kWh(self): | |
| return self.p.capacity_Ah * self.p.voltage_V / 1000 | |
| def current_capacity_kWh(self): | |
| return self.soc * self.maximal_capacity_kWh | |
| def satisfy_demand(self, demand_kW): | |
| assert 0 <= self.soc <= 1 | |
| assert demand_kW >= 0 | |
| # rate limited: | |
| possible_discharge_in_timestep_kWh = self.p.discharge_kW * self.time_interval_h | |
| # limited by current capacity: | |
| possible_discharge_in_timestep_kWh = min((possible_discharge_in_timestep_kWh, self.current_capacity_kWh)) | |
| # limited by need: | |
| discharge_in_timestep_kWh = min((possible_discharge_in_timestep_kWh, demand_kW * self.time_interval_h)) | |
| consumption_from_bess_kW = discharge_in_timestep_kWh / self.time_interval_h | |
| unsatisfied_demand_kW = demand_kW - consumption_from_bess_kW | |
| cap_of_battery_kWh = self.current_capacity_kWh - discharge_in_timestep_kWh | |
| soc = cap_of_battery_kWh / self.maximal_capacity_kWh | |
| assert 0 <= soc <= self.soc <= 1 | |
| self.soc = soc | |
| return unsatisfied_demand_kW | |
| def charge(self, charge_kW): | |
| assert 0 <= self.soc <= 1 | |
| assert charge_kW >= 0 | |
| # rate limited: | |
| possible_charge_in_timestep_kWh = self.p.charge_kW * self.time_interval_h | |
| # limited by current capacity: | |
| possible_charge_in_timestep_kWh = min((possible_charge_in_timestep_kWh, self.maximal_capacity_kWh - self.current_capacity_kWh)) | |
| # limited by supply: | |
| charge_in_timestep_kWh = min((possible_charge_in_timestep_kWh, charge_kW * self.time_interval_h)) | |
| actual_charge_kW = charge_in_timestep_kWh / self.time_interval_h | |
| unused_charge_kW = charge_kW - actual_charge_kW | |
| cap_of_battery_kWh = self.current_capacity_kWh + charge_in_timestep_kWh | |
| soc = cap_of_battery_kWh / self.maximal_capacity_kWh | |
| assert 0 <= self.soc <= soc <= 1 | |
| self.soc = soc | |
| return unused_charge_kW | |