Spaces:
Sleeping
Sleeping
Daniel Varga commited on
Commit ·
4da0b0d
1
Parent(s): 9c39ff0
demand charge measured in kwh/15min
Browse files- v2/architecture.py +10 -2
- v2/supplier.py +14 -14
v2/architecture.py
CHANGED
|
@@ -227,10 +227,16 @@ def simulator(battery_model, supplier, prod_cons, decider):
|
|
| 227 |
consumption_from_bess_series = np.array(consumption_from_bess_series)
|
| 228 |
discarded_production_series = np.array(discarded_production_series)
|
| 229 |
|
|
|
|
| 230 |
total_charge, consumption_charge_series, demand_charges = supplier.fee(
|
| 231 |
-
|
| 232 |
provide_detail=True)
|
| 233 |
print(f"All in all we have paid {total_charge} to network.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
|
| 235 |
results = pd.DataFrame({'soc_series': soc_series, 'consumption_from_solar': consumption_from_solar_series,
|
| 236 |
'consumption_from_network': consumption_from_network_series,
|
|
@@ -248,6 +254,9 @@ def main():
|
|
| 248 |
|
| 249 |
supplier = Supplier(price=100) # Ft/kWh
|
| 250 |
supplier.set_price_for_interval(9, 17, 150) # nine-to-five increased price.
|
|
|
|
|
|
|
|
|
|
| 251 |
|
| 252 |
parameters = SolarParameters()
|
| 253 |
|
|
@@ -267,7 +276,6 @@ def main():
|
|
| 267 |
results = simulator(battery_model, supplier, all_data_with_predictions, decider)
|
| 268 |
print("Simulation runtime", time.perf_counter() - t, "seconds.")
|
| 269 |
|
| 270 |
-
return
|
| 271 |
import matplotlib.pyplot as plt
|
| 272 |
results['soc_series'].plot()
|
| 273 |
plt.show()
|
|
|
|
| 227 |
consumption_from_bess_series = np.array(consumption_from_bess_series)
|
| 228 |
discarded_production_series = np.array(discarded_production_series)
|
| 229 |
|
| 230 |
+
consumption_from_network_pandas_series = pd.Series(consumption_from_network_series, index=prod_cons.index)
|
| 231 |
total_charge, consumption_charge_series, demand_charges = supplier.fee(
|
| 232 |
+
consumption_from_network_pandas_series,
|
| 233 |
provide_detail=True)
|
| 234 |
print(f"All in all we have paid {total_charge} to network.")
|
| 235 |
+
fifteen_minute_peaks = consumption_from_network_pandas_series.resample('15T').sum()
|
| 236 |
+
demand_charges = pd.Series(demand_charges, index=fifteen_minute_peaks.index)
|
| 237 |
+
demand_charges.plot()
|
| 238 |
+
import matplotlib.pyplot as plt
|
| 239 |
+
plt.show()
|
| 240 |
|
| 241 |
results = pd.DataFrame({'soc_series': soc_series, 'consumption_from_solar': consumption_from_solar_series,
|
| 242 |
'consumption_from_network': consumption_from_network_series,
|
|
|
|
| 254 |
|
| 255 |
supplier = Supplier(price=100) # Ft/kWh
|
| 256 |
supplier.set_price_for_interval(9, 17, 150) # nine-to-five increased price.
|
| 257 |
+
# peak_demand dimension is kWh, but it's interpreted as the full consumption
|
| 258 |
+
# during a 15 minute timestep.
|
| 259 |
+
supplier.set_demand_charge(peak_demand=25, surcharge_per_kwh=200) # kWh in a 15 minutes interval, Ft/kWh
|
| 260 |
|
| 261 |
parameters = SolarParameters()
|
| 262 |
|
|
|
|
| 276 |
results = simulator(battery_model, supplier, all_data_with_predictions, decider)
|
| 277 |
print("Simulation runtime", time.perf_counter() - t, "seconds.")
|
| 278 |
|
|
|
|
| 279 |
import matplotlib.pyplot as plt
|
| 280 |
results['soc_series'].plot()
|
| 281 |
plt.show()
|
v2/supplier.py
CHANGED
|
@@ -9,11 +9,11 @@ import unittest
|
|
| 9 |
class Supplier:
|
| 10 |
# price [HUF/kWh]
|
| 11 |
# peak_demand kW
|
| 12 |
-
#
|
| 13 |
def __init__(self, price):
|
| 14 |
self.hourly_prices = np.ones(168) * price
|
| 15 |
-
self.peak_demand = np.inf # no demand_charge by default
|
| 16 |
-
self.
|
| 17 |
|
| 18 |
# start and end are indices of hours starting from Monday 00:00.
|
| 19 |
def set_price_for_interval(self, start, end, price):
|
|
@@ -30,10 +30,10 @@ class Supplier:
|
|
| 30 |
h = day * 24
|
| 31 |
self.set_price_for_interval(h + start, h + end, price)
|
| 32 |
|
| 33 |
-
def set_demand_charge(self, peak_demand,
|
| 34 |
-
self.peak_demand = peak_demand # [
|
| 35 |
# the HUF charged per kW of demand exceeding peak_demand during a 15 minutes timeframe.
|
| 36 |
-
self.
|
| 37 |
|
| 38 |
@staticmethod
|
| 39 |
def hour_of_date(date):
|
|
@@ -46,12 +46,12 @@ class Supplier:
|
|
| 46 |
def price(self, date):
|
| 47 |
return self.hourly_prices[self.hour_of_date(date)]
|
| 48 |
|
| 49 |
-
# demand is the maximum demand in
|
| 50 |
-
def demand_charge(self,
|
| 51 |
-
if
|
| 52 |
return 0.0
|
| 53 |
else:
|
| 54 |
-
return (
|
| 55 |
|
| 56 |
# demand_series is pandas series indexed by time.
|
| 57 |
# during each time step demand [kW] is assumed to be constant.
|
|
@@ -70,8 +70,8 @@ class Supplier:
|
|
| 70 |
assert 15 % demand_series.index.freq.n == 0
|
| 71 |
time_steps_per_demand_charge_evaluation = 15 // demand_series.index.freq.n
|
| 72 |
# fifteen_minute_peaks [kW] tells the maximum demand in a 15 minutes timeframe:
|
| 73 |
-
|
| 74 |
-
demand_charges = [self.demand_charge(
|
| 75 |
total_demand_charge = sum(demand_charges)
|
| 76 |
total_charge = consumption_charge + total_demand_charge
|
| 77 |
if provide_detail:
|
|
@@ -131,9 +131,9 @@ class TestSupplier(unittest.TestCase):
|
|
| 131 |
expected_fee = (constant_demand * 23 + extreme_demand) * self.constant_price
|
| 132 |
self.assertEqual(self.supplier.fee(demand_series), expected_fee)
|
| 133 |
|
| 134 |
-
# now the (1000-500) kW above 500 kW is surcharged for (1000-500 kW) * 10 HUF/
|
| 135 |
# that is 500*10*4=20000 demand_charge.
|
| 136 |
-
self.supplier.set_demand_charge(peak_demand=500,
|
| 137 |
expected_fee += 20000
|
| 138 |
self.assertEqual(self.supplier.fee(demand_series), expected_fee)
|
| 139 |
|
|
|
|
| 9 |
class Supplier:
|
| 10 |
# price [HUF/kWh]
|
| 11 |
# peak_demand kW
|
| 12 |
+
# surcharge_per_kwh [HUF/kWh for each 15 minute timeframe]
|
| 13 |
def __init__(self, price):
|
| 14 |
self.hourly_prices = np.ones(168) * price
|
| 15 |
+
self.peak_demand = np.inf # [kWh] (!) no demand_charge by default
|
| 16 |
+
self.surcharge_per_kwh = 0
|
| 17 |
|
| 18 |
# start and end are indices of hours starting from Monday 00:00.
|
| 19 |
def set_price_for_interval(self, start, end, price):
|
|
|
|
| 30 |
h = day * 24
|
| 31 |
self.set_price_for_interval(h + start, h + end, price)
|
| 32 |
|
| 33 |
+
def set_demand_charge(self, peak_demand, surcharge_per_kwh):
|
| 34 |
+
self.peak_demand = peak_demand # [kWh]
|
| 35 |
# the HUF charged per kW of demand exceeding peak_demand during a 15 minutes timeframe.
|
| 36 |
+
self.surcharge_per_kwh = surcharge_per_kwh # [HUF/kWh]
|
| 37 |
|
| 38 |
@staticmethod
|
| 39 |
def hour_of_date(date):
|
|
|
|
| 46 |
def price(self, date):
|
| 47 |
return self.hourly_prices[self.hour_of_date(date)]
|
| 48 |
|
| 49 |
+
# demand is the maximum demand in kWh during a 15 minute interval
|
| 50 |
+
def demand_charge(self, demand_in_kwh):
|
| 51 |
+
if demand_in_kwh <= self.peak_demand:
|
| 52 |
return 0.0
|
| 53 |
else:
|
| 54 |
+
return (demand_in_kwh - self.peak_demand) * self.surcharge_per_kwh
|
| 55 |
|
| 56 |
# demand_series is pandas series indexed by time.
|
| 57 |
# during each time step demand [kW] is assumed to be constant.
|
|
|
|
| 70 |
assert 15 % demand_series.index.freq.n == 0
|
| 71 |
time_steps_per_demand_charge_evaluation = 15 // demand_series.index.freq.n
|
| 72 |
# fifteen_minute_peaks [kW] tells the maximum demand in a 15 minutes timeframe:
|
| 73 |
+
fifteen_minute_demands_in_kwh = demand_series.resample('15T').sum() * step_in_hour
|
| 74 |
+
demand_charges = [self.demand_charge(demand_in_kwh) for demand_in_kwh in fifteen_minute_demands_in_kwh]
|
| 75 |
total_demand_charge = sum(demand_charges)
|
| 76 |
total_charge = consumption_charge + total_demand_charge
|
| 77 |
if provide_detail:
|
|
|
|
| 131 |
expected_fee = (constant_demand * 23 + extreme_demand) * self.constant_price
|
| 132 |
self.assertEqual(self.supplier.fee(demand_series), expected_fee)
|
| 133 |
|
| 134 |
+
# now the (1000-500) kW above 500 kW is surcharged for (1000-500 kW) * 10 HUF/kWh/15mins, for 1 hour,
|
| 135 |
# that is 500*10*4=20000 demand_charge.
|
| 136 |
+
self.supplier.set_demand_charge(peak_demand=500, surcharge_per_kwh=10)
|
| 137 |
expected_fee += 20000
|
| 138 |
self.assertEqual(self.supplier.fee(demand_series), expected_fee)
|
| 139 |
|