# 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, capacity_Ah, time_interval_h): self.capacity_Ah = capacity_Ah self.efficiency = 0.9 # [dimensionless] self.voltage_V = 600 self.charge_kW = 50 self.discharge_kW = 60 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 @property def maximal_capacity_kWh(self): return self.capacity_Ah * self.voltage_V / 1000 @property 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.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.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