Daniel Varga commited on
Commit
fee109b
·
1 Parent(s): cb62f63

peak shaving, predicting t-168h value.

Browse files
Files changed (1) hide show
  1. v2/architecture.py +23 -22
v2/architecture.py CHANGED
@@ -110,23 +110,17 @@ class Decider:
110
  # the method returns a pd.Series of Decisions as integers.
111
  def decide(self, prod_pred, cons_pred, fees, battery_model):
112
  return Decision.PASSIVE
113
- next_prod = prod_pred[0]
114
- next_cons = cons_pred[0]
115
- deficit = next_cons - next_prod
116
- soc = battery_model.soc
117
- if soc > 0.9:
 
 
 
118
  return Decision.DISCHARGE
119
- elif soc < 0.1 and OLCSO:
120
  return Decision.PASSIVE
121
- return
122
-
123
- # assert len(prod_pred) == len(cons_pred) == self.input_window_size
124
- self.random_seed += 1
125
- self.random_seed %= 3 # dummy rotates between Decisions
126
- self.random_seed = Decision.DISCHARGE
127
- return self.random_seed
128
- # dummy decider always says DISCHARGE:
129
- # return pd.Series([Decision.DISCHARGE] * self.output_window_size, dtype=int)
130
 
131
 
132
  # even mock-er class than usual.
@@ -259,7 +253,7 @@ def simulator(battery_model, prod_cons, decider):
259
  fifteen_minute_surdemands_in_kwh = (fifteen_minute_demands_in_kwh - decider.precalculated_supplier.peak_demand).clip(lower=0)
260
  demand_charges = fifteen_minute_surdemands_in_kwh * decider.precalculated_supplier.surcharge_per_kwh
261
  total_charge = consumption_charge_series.sum() + demand_charges.sum()
262
- print(f"All in all we have paid {total_charge} to network.")
263
 
264
  if DO_VIS:
265
  demand_charges.plot()
@@ -286,7 +280,7 @@ def main():
286
  supplier.set_price_for_daily_interval(0, 3, 20)
287
  # peak_demand dimension is kWh, but it's interpreted as the full consumption
288
  # during a 15 minute timestep.
289
- supplier.set_demand_charge(peak_demand=25, surcharge_per_kwh=500) # kWh in a 15 minutes interval, Ft/kWh
290
 
291
  parameters = SolarParameters()
292
 
@@ -294,10 +288,19 @@ def main():
294
  add_production_field(met_2021_data, parameters)
295
  all_data = interpolate_and_join(met_2021_data, cons_2021_data)
296
 
297
- # we have perfect foresight, yet:
 
 
 
 
298
  all_data_with_predictions = all_data.copy()
299
- all_data_with_predictions['Consumption_prediction'] = all_data_with_predictions['Consumption']
300
- all_data_with_predictions['Production_prediction'] = all_data_with_predictions['Production']
 
 
 
 
 
301
 
302
  precalculated_supplier = precalculate_supplier(supplier, all_data.index)
303
  # we delete the supplier to avoid accidentally calling it instead of precalculated_supplier
@@ -305,8 +308,6 @@ def main():
305
 
306
  all_data_with_predictions['Consumption_fees'] = precalculated_supplier.consumption_fees # [HUF / kWh]
307
 
308
- time_interval_min = all_data.index.freq.n
309
- time_interval_h = time_interval_min / 60
310
  battery_model = BatteryModel(capacity_Ah=600, time_interval_h=time_interval_h)
311
 
312
  # TODO this is super unfortunate:
 
110
  # the method returns a pd.Series of Decisions as integers.
111
  def decide(self, prod_pred, cons_pred, fees, battery_model):
112
  return Decision.PASSIVE
113
+ # 15 minutes demand charge window divided by 5 minute timestep, TODO make it more principled
114
+ peak_shaving_window = 3
115
+
116
+ # TODO is there a kWh kW confusion here?:
117
+ step_in_hour = self.precalculated_supplier.time_index.freq.n / 60 # [hour], the length of a time step.
118
+ deficit_kw = (cons_pred[:peak_shaving_window] - prod_pred[:peak_shaving_window]).clip(min=0)
119
+ deficit_kwh = (step_in_hour * deficit_kw).sum()
120
+ if deficit_kwh > self.precalculated_supplier.peak_demand:
121
  return Decision.DISCHARGE
122
+ else:
123
  return Decision.PASSIVE
 
 
 
 
 
 
 
 
 
124
 
125
 
126
  # even mock-er class than usual.
 
253
  fifteen_minute_surdemands_in_kwh = (fifteen_minute_demands_in_kwh - decider.precalculated_supplier.peak_demand).clip(lower=0)
254
  demand_charges = fifteen_minute_surdemands_in_kwh * decider.precalculated_supplier.surcharge_per_kwh
255
  total_charge = consumption_charge_series.sum() + demand_charges.sum()
256
+ print(f"All in all we have paid the network {total_charge / 10 ** 6} MHUF.")
257
 
258
  if DO_VIS:
259
  demand_charges.plot()
 
280
  supplier.set_price_for_daily_interval(0, 3, 20)
281
  # peak_demand dimension is kWh, but it's interpreted as the full consumption
282
  # during a 15 minute timestep.
283
+ supplier.set_demand_charge(peak_demand=2.5, surcharge_per_kwh=500) # kWh in a 15 minutes interval, Ft/kWh
284
 
285
  parameters = SolarParameters()
286
 
 
288
  add_production_field(met_2021_data, parameters)
289
  all_data = interpolate_and_join(met_2021_data, cons_2021_data)
290
 
291
+ time_interval_min = all_data.index.freq.n
292
+ print("time_interval_min", time_interval_min)
293
+ time_interval_h = time_interval_min / 60
294
+
295
+ # we predict last week same time for consumption, and yesterday same time for production.
296
  all_data_with_predictions = all_data.copy()
297
+ cons_shift = 60 * 168 // time_interval_min
298
+ prod_shift = 60 * 24 // time_interval_min
299
+ all_data_with_predictions['Consumption_prediction'] = all_data_with_predictions['Consumption'].shift(periods=cons_shift)
300
+ all_data_with_predictions['Production_prediction'] = all_data_with_predictions['Production'].shift(periods=prod_shift)
301
+ # we predict zero before we have data, no big deal:
302
+ all_data_with_predictions['Consumption_prediction'][:cons_shift] = 0
303
+ all_data_with_predictions['Production_prediction'][:prod_shift] = 0
304
 
305
  precalculated_supplier = precalculate_supplier(supplier, all_data.index)
306
  # we delete the supplier to avoid accidentally calling it instead of precalculated_supplier
 
308
 
309
  all_data_with_predictions['Consumption_fees'] = precalculated_supplier.consumption_fees # [HUF / kWh]
310
 
 
 
311
  battery_model = BatteryModel(capacity_Ah=600, time_interval_h=time_interval_h)
312
 
313
  # TODO this is super unfortunate: