Example #1
0
    def __init__(
            self,
            initial_rate,
            final_rate,
            fit_to_limit=True,
            energy_rate_change_per_update=None,
            update_interval=duration(
                minutes=ConstSettings.GeneralSettings.DEFAULT_UPDATE_INTERVAL),
            rate_limit_object=max):
        self.fit_to_limit = fit_to_limit
        self.initial_rate_profile_buffer = read_arbitrary_profile(
            InputProfileTypes.IDENTITY, initial_rate)
        self.initial_rate = {}
        self.final_rate_profile_buffer = read_arbitrary_profile(
            InputProfileTypes.IDENTITY, final_rate)
        self.final_rate = {}
        if fit_to_limit is False:
            self.energy_rate_change_per_update_profile_buffer = \
                read_arbitrary_profile(InputProfileTypes.IDENTITY, energy_rate_change_per_update)
        else:
            self.energy_rate_change_per_update_profile_buffer = {}

        self.energy_rate_change_per_update = {}
        self.update_interval = update_interval
        self.update_counter = {}
        self.number_of_available_updates = 0
        self.rate_limit_object = rate_limit_object
def test_if_storage_doesnt_buy_too_expensive(storage_strategy_test3,
                                             area_test3):
    storage_strategy_test3.bid_update.initial_rate = \
        read_arbitrary_profile(InputProfileTypes.IDENTITY, 0)
    storage_strategy_test3.bid_update.final_rate = \
        read_arbitrary_profile(InputProfileTypes.IDENTITY, 1)
    storage_strategy_test3.event_activate()
    storage_strategy_test3.event_tick()
    assert len(storage_strategy_test3.accept_offer.calls) == 0
Example #3
0
 def _populate_buying_rate(self):
     if self.buying_rate_profile is not None:
         self.energy_buy_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, self.buying_rate_profile)
         # TODO: to be checked via deleting in case increased memory is observed during runtime
         del self.buying_rate_profile
     elif self.energy_buy_rate is not None:
         self.energy_buy_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, self.energy_buy_rate)
     else:
         self.energy_buy_rate = self.area.config.market_maker_rate
Example #4
0
    def _area_reconfigure_prices(self, **kwargs):
        if key_in_dict_and_not_none(kwargs, 'initial_selling_rate'):
            initial_rate = read_arbitrary_profile(
                InputProfileTypes.IDENTITY, kwargs['initial_selling_rate'])
        else:
            initial_rate = self.offer_update.initial_rate_profile_buffer

        if key_in_dict_and_not_none(kwargs, 'final_selling_rate'):
            final_rate = read_arbitrary_profile(InputProfileTypes.IDENTITY,
                                                kwargs['final_selling_rate'])
        else:
            final_rate = self.offer_update.final_rate_profile_buffer
        if key_in_dict_and_not_none(kwargs, 'energy_rate_decrease_per_update'):
            energy_rate_change_per_update = \
                read_arbitrary_profile(InputProfileTypes.IDENTITY,
                                       kwargs['energy_rate_decrease_per_update'])
        else:
            energy_rate_change_per_update = \
                self.offer_update.energy_rate_change_per_update_profile_buffer
        if key_in_dict_and_not_none(kwargs, 'fit_to_limit'):
            fit_to_limit = kwargs['fit_to_limit']
        else:
            fit_to_limit = self.offer_update.fit_to_limit
        if key_in_dict_and_not_none(kwargs, 'update_interval'):
            if isinstance(kwargs['update_interval'], int):
                update_interval = duration(minutes=kwargs['update_interval'])
            else:
                update_interval = kwargs['update_interval']
        else:
            update_interval = self.offer_update.update_interval
        if key_in_dict_and_not_none(kwargs, 'use_market_maker_rate'):
            self.use_market_maker_rate = kwargs['use_market_maker_rate']

        try:
            self._validate_rates(initial_rate, final_rate,
                                 energy_rate_change_per_update, fit_to_limit)
        except Exception as e:
            log.error(
                f"PVStrategy._area_reconfigure_prices failed. Exception: {e}. "
                f"Traceback: {traceback.format_exc()}")
            return

        self.offer_update.set_parameters(
            initial_rate_profile_buffer=initial_rate,
            final_rate_profile_buffer=final_rate,
            energy_rate_change_per_update_profile_buffer=
            energy_rate_change_per_update,
            fit_to_limit=fit_to_limit,
            update_interval=update_interval)
Example #5
0
    def _read_predefined_profile_for_pv(self):
        """
        Reads profile data from the predefined power profiles. Reads config and constructor
        parameters and selects the appropriate predefined profile.
        """
        if self._power_profile_index is None or self._power_profile_index == 4:
            if self.owner.config.pv_user_profile is not None:
                return self.owner.config.pv_user_profile
            else:
                self._power_profile_index = self.owner.config.cloud_coverage
        if self._power_profile_index == 0:  # 0:sunny
            profile_path = pathlib.Path(d3a_path +
                                        '/resources/Solar_Curve_W_sunny.csv')
        elif self._power_profile_index == 1:  # 1:partial
            profile_path = pathlib.Path(d3a_path +
                                        '/resources/Solar_Curve_W_partial.csv')
        elif self._power_profile_index == 2:  # 2:cloudy
            profile_path = pathlib.Path(d3a_path +
                                        '/resources/Solar_Curve_W_cloudy.csv')
        else:
            raise ValueError("Energy_profile has to be in [0,1,2,4]")

        # Populate energy production forecast data
        self.power_profile = read_arbitrary_profile(InputProfileTypes.POWER,
                                                    str(profile_path))
Example #6
0
 def _read_predefined_profile_for_pv(self):
     """
     Reads profile data from the power profile. Handles csv files and dicts.
     :return: key value pairs of time to energy in kWh
     """
     self.power_profile = read_arbitrary_profile(InputProfileTypes.POWER,
                                                 self._power_profile_W)
Example #7
0
def test_profile_with_date_and_seconds_can_be_parsed():
    GlobalConfig.slot_length = duration(minutes=15)
    profile_date = datetime(year=2019, month=3, day=2)
    GlobalConfig.start_date = profile_date
    profile_path = pathlib.Path(d3a_path +
                                '/resources/datetime_seconds_profile.csv')
    profile = read_arbitrary_profile(InputProfileTypes.POWER,
                                     str(profile_path))
    # After the 6th element the rest of the entries are populated with the last value
    expected_energy_values = [1.5, 1.25, 1.0, 0.75, 0.5, 0.25]
    if GlobalConfig.IS_CANARY_NETWORK:
        energy_values_profile = []
        energy_values_after_profile = []
        end_time = profile_date.add(minutes=GlobalConfig.slot_length.minutes *
                                    6)
        for time, v in profile.items():
            if v > 0:
                if time.weekday() == profile_date.weekday(
                ) and time.time() < end_time.time():
                    energy_values_profile.append(v)
                else:
                    energy_values_after_profile.append(v)
        assert energy_values_profile == expected_energy_values
        all(x == 0.25 for x in energy_values_after_profile)
    else:
        assert list(profile.values())[:6] == expected_energy_values
        assert all(x == 0.25 for x in list(profile.values())[6:])

    GlobalConfig.start_date = today(tz=TIME_ZONE)
Example #8
0
 def _event_activate_energy(self, daily_load_profile):
     """
     Reads the power profile data and calculates the required energy
     for each slot.
     """
     self.load_profile = read_arbitrary_profile(InputProfileTypes.POWER,
                                                daily_load_profile)
Example #9
0
def hour_profile_of_market_maker_rate(context, scenario):
    import importlib
    from d3a_interface.read_user_profile import InputProfileTypes
    setup_file_module = importlib.import_module(
        "d3a.setup.{}".format(scenario))
    context._market_maker_rate = \
        read_arbitrary_profile(InputProfileTypes.IDENTITY, setup_file_module.market_maker_rate)

    assert context._market_maker_rate is not None
Example #10
0
def check_load_profile_csv(context, single_or_multi):
    house1 = next(filter(lambda x: x.name == "House 1", context.simulation.area.children))
    load = next(filter(lambda x: x.name == "H1 DefinedLoad", house1.children))
    if single_or_multi == "single":
        path = user_profile_load_csv.profile_path
    else:
        path = user_profile_load_csv_multiday.profile_path
    input_profile = read_arbitrary_profile(InputProfileTypes.POWER, path)
    for timepoint, energy in load.strategy.state._desired_energy_Wh.items():
        assert energy == find_object_of_same_weekday_and_time(input_profile, timepoint) * 1000
Example #11
0
def test_correct_interpolation_power_profile():
    slot_length = 20
    GlobalConfig.slot_length = duration(minutes=slot_length)
    profile_path = pathlib.Path(d3a_path +
                                '/resources/Solar_Curve_W_sunny.csv')
    profile = read_arbitrary_profile(InputProfileTypes.POWER,
                                     str(profile_path))
    times = list(profile)
    for ii in range(len(times) - 1):
        assert abs(
            (times[ii] - times[ii + 1]).in_seconds()) == slot_length * 60
Example #12
0
def test_correct_time_expansion_read_arbitrary_profile():
    market_maker_rate = 30
    if GlobalConfig.IS_CANARY_NETWORK:
        GlobalConfig.sim_duration = duration(hours=3)
        expected_last_time_slot = today(tz=TIME_ZONE).add(
            days=CN_PROFILE_EXPANSION_DAYS - 1, hours=23, minutes=45)
        mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY,
                                     market_maker_rate)
        assert list(mmr.keys())[-1] == expected_last_time_slot
        GlobalConfig.sim_duration = duration(hours=30)
        expected_last_time_slot = today(tz=TIME_ZONE).add(
            days=CN_PROFILE_EXPANSION_DAYS - 1, hours=23, minutes=45)
        mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY,
                                     market_maker_rate)
        assert list(mmr.keys())[-1] == expected_last_time_slot
    else:
        GlobalConfig.sim_duration = duration(hours=3)
        mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY,
                                     market_maker_rate)
        assert (list(mmr.keys())[-1] - today(tz=TIME_ZONE)).days == 0
        GlobalConfig.sim_duration = duration(hours=36)
        mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY,
                                     market_maker_rate)
        assert (list(mmr.keys())[-1] - today(tz=TIME_ZONE)).days == 1
        GlobalConfig.sim_duration = duration(hours=48)
        mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY,
                                     market_maker_rate)
        assert list(mmr.keys())[-1] == today(tz=TIME_ZONE).add(days=1,
                                                               hours=23,
                                                               minutes=45)
        GlobalConfig.sim_duration = duration(hours=49)
        mmr = read_arbitrary_profile(InputProfileTypes.IDENTITY,
                                     market_maker_rate)
        assert list(mmr.keys())[-1] == today(tz=TIME_ZONE).add(days=2,
                                                               minutes=45)
Example #13
0
def check_pv_csv_profile(context):
    house1 = list(
        filter(lambda x: x.name == "House 1",
               context.simulation.area.children))[0]
    pv = list(filter(lambda x: x.name == "H1 PV", house1.children))[0]
    from d3a.setup.strategy_tests.user_profile_pv_csv import user_profile_path
    profile_data = read_arbitrary_profile(InputProfileTypes.POWER,
                                          user_profile_path)
    for timepoint, energy in pv.strategy.state._energy_production_forecast_kWh.items(
    ):
        if timepoint in profile_data.keys():
            assert energy == profile_data[timepoint]
        else:
            assert energy == 0
Example #14
0
def check_pv_profile_csv(context):
    house1 = list(
        filter(lambda x: x.name == "House 1",
               context.simulation.area.children))[0]
    pv = list(filter(lambda x: x.name == "H1 PV", house1.children))[0]
    input_profile = read_arbitrary_profile(InputProfileTypes.POWER,
                                           context._device_profile)
    produced_energy = {
        from_format(f'{TODAY_STR}T{k.hour:02}:{k.minute:02}',
                    DATE_TIME_FORMAT): v
        for k, v in pv.strategy.state._energy_production_forecast_kWh.items()
    }
    for timepoint, energy in produced_energy.items():
        if timepoint in input_profile:
            assert energy == input_profile[timepoint]
        else:
            assert False
Example #15
0
def check_pv_profile(context):
    house1 = list(
        filter(lambda x: x.name == "House 1",
               context.simulation.area.children))[0]
    pv = list(filter(lambda x: x.name == "H1 PV", house1.children))[0]
    if pv.strategy._power_profile_index == 0:
        path = os.path.join(d3a_path, "resources/Solar_Curve_W_sunny.csv")
    if pv.strategy._power_profile_index == 1:
        path = os.path.join(d3a_path, "resources/Solar_Curve_W_partial.csv")
    if pv.strategy._power_profile_index == 2:
        path = os.path.join(d3a_path, "resources/Solar_Curve_W_cloudy.csv")
    profile_data = read_arbitrary_profile(InputProfileTypes.POWER, str(path))
    for timepoint, energy in pv.strategy.state._energy_production_forecast_kWh.items(
    ):
        if timepoint in profile_data.keys():
            assert energy == profile_data[timepoint]
        else:
            assert energy == 0
Example #16
0
 def event_activate(self, **kwargs):
     super().event_activate()
     self.max_available_power_kW = \
         read_arbitrary_profile(InputProfileTypes.IDENTITY, self.max_available_power_kW)
Example #17
0
 def event_activate(self, **kwargs):
     self.energy_rate = self.area.config.market_maker_rate if self.energy_rate is None \
         else read_arbitrary_profile(InputProfileTypes.IDENTITY, self.energy_rate)
Example #18
0
 def _set_market_maker_rate(self):
     if self.energy_rate_profile is not None:
         GlobalConfig.market_maker_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, self.energy_rate_profile)
     elif self.energy_rate is not None:
         GlobalConfig.market_maker_rate = self.energy_rate
Example #19
0
 def _validate_constructor_arguments(initial_soc=None,
                                     min_allowed_soc=None,
                                     battery_capacity_kWh=None,
                                     max_abs_battery_power_kW=None,
                                     initial_selling_rate=None,
                                     final_selling_rate=None,
                                     initial_buying_rate=None,
                                     final_buying_rate=None,
                                     energy_rate_change_per_update=None):
     if battery_capacity_kWh is not None and battery_capacity_kWh < 0:
         raise ValueError("Battery capacity should be a positive integer")
     if max_abs_battery_power_kW is not None and max_abs_battery_power_kW < 0:
         raise ValueError(
             "Battery Power rating must be a positive integer.")
     if initial_soc is not None and 0 < initial_soc > 100:
         raise ValueError("initial SOC must be in between 0-100 %")
     if min_allowed_soc is not None and 0 < min_allowed_soc > 100:
         raise ValueError("initial SOC must be in between 0-100 %")
     if initial_soc is not None and min_allowed_soc is not None and \
             initial_soc < min_allowed_soc:
         raise ValueError(
             "Initial charge must be more than the minimum allowed soc.")
     if initial_selling_rate is not None and initial_selling_rate < 0:
         raise ValueError("Initial selling rate must be greater equal 0.")
     if final_selling_rate is not None:
         if type(final_selling_rate) is float and final_selling_rate < 0:
             raise ValueError("Final selling rate must be greater equal 0.")
         elif type(final_selling_rate) is dict and \
                 any(rate < 0 for _, rate in final_selling_rate.items()):
             raise ValueError("Final selling rate must be greater equal 0.")
     if initial_selling_rate is not None and final_selling_rate is not None:
         initial_selling_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, initial_selling_rate)
         final_selling_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, final_selling_rate)
         if any(initial_selling_rate[hour] < final_selling_rate[hour]
                for hour, _ in initial_selling_rate.items()):
             raise ValueError(
                 "Initial selling rate must be greater than final selling rate."
             )
     if initial_buying_rate is not None and initial_buying_rate < 0:
         raise ValueError("Initial buying rate must be greater equal 0.")
     if final_buying_rate is not None:
         final_buying_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, final_buying_rate)
         if any(rate < 0 for _, rate in final_buying_rate.items()):
             raise ValueError("Final buying rate must be greater equal 0.")
     if initial_buying_rate is not None and final_buying_rate is not None:
         initial_buying_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, initial_buying_rate)
         final_buying_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, final_buying_rate)
         if any(initial_buying_rate[hour] > final_buying_rate[hour]
                for hour, _ in initial_buying_rate.items()):
             raise ValueError(
                 "Initial buying rate must be less than final buying rate.")
     if final_selling_rate is not None and final_buying_rate is not None:
         final_selling_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, final_selling_rate)
         final_buying_rate = read_arbitrary_profile(
             InputProfileTypes.IDENTITY, final_buying_rate)
         if any(final_buying_rate[hour] >= final_selling_rate[hour]
                for hour, _ in final_selling_rate.items()):
             raise ValueError(
                 "final_buying_rate should be higher than final_selling_rate."
             )
     if energy_rate_change_per_update is not None and energy_rate_change_per_update < 0:
         raise ValueError(
             "energy_rate_change_per_update should be a non-negative value."
         )
Example #20
0
 def read_pv_user_profile(self, pv_user_profile=None):
     self.pv_user_profile = None \
         if pv_user_profile is None \
         else read_arbitrary_profile(InputProfileTypes.POWER,
                                     ast.literal_eval(pv_user_profile))
Example #21
0
def _read_solar_profile(profile_path):
    return read_arbitrary_profile(InputProfileTypes.POWER, str(profile_path))