示例#1
0
 def __init__(self, job_id, initial_params, area):
     self.job_id = job_id
     self.random_seed = initial_params["seed"] if initial_params[
         "seed"] is not None else ''
     self.status = {}
     self.eta = duration(seconds=0)
     self.unmatched_loads = {}
     self.unmatched_loads_redis = {}
     self.export_unmatched_loads = ExportUnmatchedLoads(area)
     self.market_unmatched_loads = MarketUnmatchedLoads()
     self.cumulative_loads = {}
     self.price_energy_day = MarketPriceEnergyDay()
     self.cumulative_grid_trades = {}
     self.accumulated_trades = {}
     self.accumulated_trades_redis = {}
     self.accumulated_balancing_trades = {}
     self.cumulative_grid_trades_redis = {}
     self.cumulative_grid_balancing_trades = {}
     self.tree_summary = {}
     self.tree_summary_redis = {}
     self.market_bills = MarketEnergyBills()
     self.balancing_bills = MarketEnergyBills(is_spot_market=False)
     self.trade_details = {}
     self.device_statistics = DeviceStatistics()
     self.energy_trade_profile = {}
     self.energy_trade_profile_redis = {}
     self.file_export_endpoints = FileExportEndpoints()
示例#2
0
    def test_export_unmatched_loads_reports_cell_tower_areas(self):
        house1 = Area("House1", [self.area1, self.area2])
        ct_strategy = MagicMock(spec=CellTowerLoadHoursStrategy)
        ct_strategy.state = MagicMock(spec=LoadState)
        ct_strategy.state.desired_energy_Wh = {}
        cell_tower = Area("Cell Tower", strategy=ct_strategy)
        self.grid = Area("Grid", [house1, cell_tower])
        for i in range(1, 11):
            timeslot = today(tz=TIME_ZONE).add(hours=12 + i)
            self.strategy1.state.desired_energy_Wh[timeslot] = 100
            self.strategy2.state.desired_energy_Wh[timeslot] = 100

            mock_market = MagicMock(spec=Market)
            mock_market.time_slot = timeslot
            mock_market.traded_energy = {"load1": -0.09, "load2": -0.099}
            house1._markets.past_markets[timeslot] = mock_market

            mock_market_ct = MagicMock(spec=Market)
            mock_market_ct.time_slot = timeslot
            mock_market_ct.traded_energy = {"Cell Tower": -0.4}
            ct_strategy.state.desired_energy_Wh[timeslot] = 1000
            cell_tower._markets.past_markets[timeslot] = mock_market_ct

            self.grid._markets.past_markets[timeslot] = mock_market

        unmatched_loads, unmatched_loads_redis = \
            ExportUnmatchedLoads(self.grid).get_current_market_results(all_past_markets=True)
        assert get_number_of_unmatched_loads(unmatched_loads) == 30
示例#3
0
def check_buy_behaviour_ib(context):
    grid = context.simulation.area
    bus = list(filter(lambda x: x.name == "Infinite Bus", grid.children))[0]
    house_1 = list(filter(lambda x: x.name == "House 1", grid.children))[0]
    pv = list(filter(lambda x: x.name == "H1 PV", house_1.children))[0]
    load = list(filter(lambda x: x.name == "H1 General Load",
                       house_1.children))[0]

    for market in grid.past_markets:
        for trade in market.trades:
            assert limit_float_precision(trade.offer.price / trade.offer.energy) <= \
                   bus.strategy.energy_rate[market.time_slot] + house_1.transfer_fee_const or \
                   "Infinite Bus" is not trade.seller

            if trade.buyer == load.name:
                assert trade.offer.energy == load.strategy.avg_power_W / 1000.
            elif trade.seller == bus.name:
                assert isclose(
                    trade.offer.energy, load.strategy.avg_power_W / 1000. -
                    pv.strategy.energy_production_forecast_kWh[
                        market.time_slot])

    unmatched, unmatched_redis = \
        ExportUnmatchedLoads(context.simulation.area).get_current_market_results(
            all_past_markets=True)
    assert get_number_of_unmatched_loads(unmatched) == 0
示例#4
0
def check_user_rate_profile_dict(context):
    house = next(
        filter(lambda x: x.name == "House 1",
               context.simulation.area.children))

    unmatched, unmatched_redis = \
        ExportUnmatchedLoads(context.simulation.area).get_current_market_results(
            all_past_markets=True)
    number_of_loads = 2
    # There are two loads with the same final_buying_rate profile that should report unmatched
    # energy demand for the first 6 hours of the day:
    assert get_number_of_unmatched_loads(unmatched) == int(
        number_of_loads * 6. * 60 / house.config.slot_length.minutes)
示例#5
0
 def test_export_unmatched_loads_is_reporting_correctly_the_device_types(self):
     self.area1.display_type = "Area 1 type"
     self.area3.display_type = "Area 3 type"
     house1 = Area("House1", [self.area1, self.area3])
     self.grid = Area("Grid", [house1])
     unmatched_loads, unmatched_loads_redis = \
         ExportUnmatchedLoads(self.grid).get_current_market_results(all_past_markets=True)
     assert get_number_of_unmatched_loads(unmatched_loads) == 0
     assert "type" not in unmatched_loads["House1"]
     assert unmatched_loads["House1"]["load1"]["type"] == "Area 1 type"
     assert unmatched_loads["House1"]["load3"]["type"] == "Area 3 type"
     assert unmatched_loads_redis[house1.uuid]["load1"]["type"] == "Area 1 type"
     assert unmatched_loads_redis[house1.uuid]["load3"]["type"] == "Area 3 type"
     assert "type" not in unmatched_loads["Grid"]
     assert unmatched_loads["Grid"]["House1"]["type"] == "Area"
     assert unmatched_loads_redis[self.grid.uuid]["House1"]["type"] == "Area"
示例#6
0
 def test_export_unmatched_loads_is_reported_correctly_for_predefined_load_strategy(self):
     house1 = Area("House1", [self.area1, self.area3])
     self.grid = Area("Grid", [house1])
     self.grid._markets.past_markets = {}
     for i in range(1, 11):
         timeslot = today(tz=TIME_ZONE).add(hours=12+i)
         mock_market = MagicMock(spec=Market)
         mock_market.time_slot = timeslot
         self.strategy1.state.desired_energy_Wh[timeslot] = 100
         self.strategy3.state.desired_energy_Wh[timeslot] = 80
         mock_market.traded_energy = {"load1": -0.099, "load3": -0.079}
         house1._markets.past_markets[timeslot] = mock_market
         self.grid._markets.past_markets[timeslot] = mock_market
     unmatched_loads, unmatched_loads_redis = \
         ExportUnmatchedLoads(self.grid).get_current_market_results(all_past_markets=True)
     assert get_number_of_unmatched_loads(unmatched_loads) == 20
示例#7
0
    def test_export_unmatched_loads_is_reported_correctly_for_all_loads_matched(self):
        house1 = Area("House1", [self.area1, self.area2])
        self.grid = Area("Grid", [house1])
        self.grid._markets.past_markets = {}
        for i in range(1, 11):
            timeslot = today(tz=TIME_ZONE).add(hours=12+i)
            self.strategy1.state.desired_energy_Wh[timeslot] = 100
            self.strategy2.state.desired_energy_Wh[timeslot] = 100
            mock_market = MagicMock(spec=Market)
            mock_market.time_slot = timeslot
            mock_market.traded_energy = {"load1": -0.101, "load2": -0.101}
            house1._markets.past_markets[timeslot] = mock_market
            self.grid._markets.past_markets[timeslot] = mock_market

        unmatched_loads, unmatched_loads_redis = \
            ExportUnmatchedLoads(self.grid).get_current_market_results(all_past_markets=True)

        assert list(unmatched_loads[self.grid.name].keys()) == ['House1']
        assert get_number_of_unmatched_loads(unmatched_loads) == 0
示例#8
0
def test_output(context, scenario, sim_duration, slot_length, tick_length):

    if scenario in ["default_2a", "default_2b", "default_3"]:
        unmatched_loads, unmatched_loads_redis = \
            ExportUnmatchedLoads(context.simulation.area).get_current_market_results(
                all_past_markets=True)
        assert get_number_of_unmatched_loads(unmatched_loads) == 0
    # (check if number of last slot is the maximal number of slots):
    no_of_slots = int(int(sim_duration) * 60 / int(slot_length))
    assert no_of_slots == context.simulation.area.current_slot
    if scenario == "default":
        street1 = list(
            filter(lambda x: x.name == "Street 1",
                   context.simulation.area.children))[0]
        house1 = list(
            filter(lambda x: x.name == "S1 House 1", street1.children))[0]
        permanent_load = list(
            filter(lambda x: x.name == "S1 H1 Load", house1.children))[0]
        energy_profile = [
            ki
            for ki in permanent_load.strategy.state.desired_energy_Wh.values()
        ]
        assert all(
            [permanent_load.strategy.energy == ei for ei in energy_profile])
示例#9
0
def no_unmatched_loads(context):
    unmatched, unmatched_redis = \
        ExportUnmatchedLoads(context.simulation.area).get_current_market_results(
            all_past_markets=True)
    assert get_number_of_unmatched_loads(unmatched) == 0
示例#10
0
class SimulationEndpointBuffer:
    def __init__(self, job_id, initial_params, area):
        self.job_id = job_id
        self.random_seed = initial_params["seed"] if initial_params[
            "seed"] is not None else ''
        self.status = {}
        self.eta = duration(seconds=0)
        self.unmatched_loads = {}
        self.unmatched_loads_redis = {}
        self.export_unmatched_loads = ExportUnmatchedLoads(area)
        self.market_unmatched_loads = MarketUnmatchedLoads()
        self.cumulative_loads = {}
        self.price_energy_day = MarketPriceEnergyDay()
        self.cumulative_grid_trades = {}
        self.accumulated_trades = {}
        self.accumulated_trades_redis = {}
        self.accumulated_balancing_trades = {}
        self.cumulative_grid_trades_redis = {}
        self.cumulative_grid_balancing_trades = {}
        self.tree_summary = {}
        self.tree_summary_redis = {}
        self.market_bills = MarketEnergyBills()
        self.balancing_bills = MarketEnergyBills(is_spot_market=False)
        self.trade_details = {}
        self.device_statistics = DeviceStatistics()
        self.energy_trade_profile = {}
        self.energy_trade_profile_redis = {}
        self.file_export_endpoints = FileExportEndpoints()

    def generate_result_report(self):
        return {
            "job_id": self.job_id,
            "random_seed": self.random_seed,
            "unmatched_loads": self.unmatched_loads_redis,
            "cumulative_loads": self.cumulative_loads,
            "price_energy_day": self.price_energy_day.redis_output,
            "cumulative_grid_trades": self.cumulative_grid_trades_redis,
            "bills": self.market_bills.bills_redis_results,
            "tree_summary": self.tree_summary_redis,
            "status": self.status,
            "eta_seconds": self.eta.seconds,
            "device_statistics": self.device_statistics.flat_results_time_str,
            "energy_trade_profile": self.energy_trade_profile_redis
        }

    def generate_json_report(self):
        return {
            "job_id": self.job_id,
            "random_seed": self.random_seed,
            "unmatched_loads": self.unmatched_loads,
            "cumulative_loads": self.cumulative_loads,
            "price_energy_day": self.price_energy_day.csv_output,
            "cumulative_grid_trades": self.cumulative_grid_trades,
            "bills": self.market_bills.bills_results,
            "tree_summary": self.tree_summary,
            "status": self.status,
            "device_statistics": self.device_statistics.device_stats_time_str,
            "energy_trade_profile": self.energy_trade_profile
        }

    def _update_unmatched_loads(self, area):
        if self.export_unmatched_loads.load_count == 0:
            self.unmatched_loads, self.unmatched_loads_redis =\
                self.market_unmatched_loads.write_none_to_unmatched_loads(area, {}, {})
        else:
            current_results, current_results_uuid = \
                self.export_unmatched_loads.get_current_market_results(
                    all_past_markets=ConstSettings.GeneralSettings.KEEP_PAST_MARKETS)

            if ConstSettings.GeneralSettings.KEEP_PAST_MARKETS:
                self.unmatched_loads = current_results
                self.unmatched_loads_redis = current_results_uuid
            else:
                self.unmatched_loads, self.unmatched_loads_redis = \
                    self.market_unmatched_loads.update_and_get_unmatched_loads(
                        current_results, current_results_uuid)

    def _update_cumulative_grid_trades(self, area):
        market_type = \
            "past_markets" if ConstSettings.GeneralSettings.KEEP_PAST_MARKETS else "current_market"
        balancing_market_type = "past_balancing_markets" \
            if ConstSettings.GeneralSettings.KEEP_PAST_MARKETS \
            else "current_balancing_market"

        if ConstSettings.GeneralSettings.KEEP_PAST_MARKETS:
            self.accumulated_trades = {}
            self.accumulated_trades_redis = {}
            self.accumulated_balancing_trades = {}

        self.accumulated_trades_redis, self.cumulative_grid_trades_redis = \
            export_cumulative_grid_trades_redis(area, self.accumulated_trades_redis,
                                                market_type)
        self.accumulated_trades, self.cumulative_grid_trades = \
            export_cumulative_grid_trades(area, self.accumulated_trades,
                                          market_type, all_devices=True)
        self.accumulated_balancing_trades, self.cumulative_grid_balancing_trades = \
            export_cumulative_grid_trades(area, self.accumulated_balancing_trades,
                                          balancing_market_type)

    def update_stats(self, area, simulation_status, eta):
        self.status = simulation_status
        self.eta = eta
        self._update_unmatched_loads(area)
        # Should always precede tree-summary update
        self.price_energy_day.update(area)
        self.cumulative_loads = {
            "price-currency": "Euros",
            "load-unit": "kWh",
            "cumulative-load-price": export_cumulative_loads(area)
        }

        self._update_cumulative_grid_trades(area)

        self.market_bills.update(area)
        self.balancing_bills.update(area)

        self._update_tree_summary(area)
        self.trade_details = generate_inter_area_trade_details(
            area, "past_markets")

        self.device_statistics.update(area)

        self.file_export_endpoints(area)
        self.energy_trade_profile = self.file_export_endpoints.traded_energy_profile
        self.energy_trade_profile_redis = self._round_energy_trade_profile(
            self.file_export_endpoints.traded_energy_profile_redis)

    def _update_tree_summary(self, area):
        price_energy_list = self.price_energy_day.csv_output

        def calculate_prices(key, functor):
            if area.name not in price_energy_list:
                return 0.
            energy_prices = [
                price_energy[key] for price_energy in price_energy_list[
                    area.name]["price-energy-day"]
            ]
            return round(functor(energy_prices),
                         2) if len(energy_prices) > 0 else 0.0

        self.tree_summary[area.slug] = {
            "min_trade_price": calculate_prices("min_price", min),
            "max_trade_price": calculate_prices("max_price", max),
            "avg_trade_price": calculate_prices("av_price", mean),
        }
        self.tree_summary_redis[area.uuid] = self.tree_summary[area.slug]
        for child in area.children:
            if child.children:
                self._update_tree_summary(child)

    @classmethod
    def _round_energy_trade_profile(cls, profile):
        for k in profile.keys():
            for sold_bought in ['sold_energy', 'bought_energy']:
                for dev in profile[k][sold_bought].keys():
                    for target in profile[k][sold_bought][dev].keys():
                        for timestamp in profile[k][sold_bought][dev][
                                target].keys():
                            profile[k][sold_bought][dev][target][
                                timestamp] = round_floats_for_ui(
                                    profile[k][sold_bought][dev][target]
                                    [timestamp])
        return profile