Exemplo n.º 1
0
 def _set_alternative_pricing_scheme(self):
     if ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME != 0:
         if ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME == 1:
             for time_slot in generate_market_slot_list():
                 self.bid_update.reassign_mixin_arguments(time_slot,
                                                          initial_rate=0,
                                                          final_rate=0)
                 self.offer_update.reassign_mixin_arguments(time_slot,
                                                            initial_rate=0,
                                                            final_rate=0)
         elif ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME == 2:
             for time_slot in generate_market_slot_list():
                 rate = \
                     self.area.config.market_maker_rate[time_slot] * \
                     ConstSettings.IAASettings.AlternativePricing.FEED_IN_TARIFF_PERCENTAGE / \
                     100
                 self.bid_update.reassign_mixin_arguments(time_slot,
                                                          initial_rate=0,
                                                          final_rate=rate)
                 self.offer_update.reassign_mixin_arguments(
                     time_slot, initial_rate=rate, final_rate=rate)
         elif ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME == 3:
             for time_slot in generate_market_slot_list():
                 rate = self.area.config.market_maker_rate[time_slot]
                 self.bid_update.reassign_mixin_arguments(time_slot,
                                                          initial_rate=0,
                                                          final_rate=rate)
                 self.offer_update.reassign_mixin_arguments(
                     time_slot, initial_rate=rate, final_rate=rate)
         else:
             raise MarketException
Exemplo n.º 2
0
    def update_sold_bought_energy(self, area: Area):
        if ConstSettings.GeneralSettings.KEEP_PAST_MARKETS:
            self.traded_energy[area.uuid] = \
                self._calculate_devices_sold_bought_energy_past_markets(area, area.past_markets)
            self.traded_energy[area.name] = self.traded_energy[area.uuid]
            self.balancing_traded_energy[area.name] = \
                self._calculate_devices_sold_bought_energy_past_markets(
                    area, area.past_balancing_markets)
            self.traded_energy_profile_redis[area.uuid] = \
                self._serialize_traded_energy_lists(self.traded_energy, area.uuid)
            self.traded_energy_profile[
                area.slug] = self.traded_energy_profile_redis[area.uuid]
        else:
            if area.uuid not in self.traded_energy:
                self.traded_energy[area.uuid] = {
                    "sold_energy": {},
                    "bought_energy": {}
                }
            self._calculate_devices_sold_bought_energy(
                self.traded_energy[area.uuid], area.current_market)
            self.traded_energy[area.name] = self.traded_energy[area.uuid]
            if area.name not in self.balancing_traded_energy:
                self.balancing_traded_energy[area.name] = {
                    "sold_energy": {},
                    "bought_energy": {}
                }
            if len(area.past_balancing_markets) > 0:
                self._calculate_devices_sold_bought_energy(
                    self.balancing_traded_energy[area.name],
                    area.current_balancing_market)

            if area.uuid not in self.traded_energy_current:
                self.traded_energy_current[area.uuid] = {
                    "sold_energy": {},
                    "bought_energy": {}
                }
            if area.current_market is not None:
                self.time_slots = [area.current_market.time_slot]
                self._calculate_devices_sold_bought_energy(
                    self.traded_energy_current[area.uuid], area.current_market)
                self.traded_energy_current[
                    area.uuid] = self._serialize_traded_energy_lists(
                        self.traded_energy_current, area.uuid)
                self.time_slots = generate_market_slot_list(area)

            self.balancing_traded_energy[
                area.uuid] = self.balancing_traded_energy[area.name]

            # TODO: Adapt to not store the full results on D3A.
            self.traded_energy_profile_redis = merge_energy_trade_profile_to_global(
                self.traded_energy_current, self.traded_energy_profile_redis,
                generate_market_slot_list(area))
            self.traded_energy_profile[
                area.slug] = self.traded_energy_profile_redis[area.uuid]
Exemplo n.º 3
0
    def __init__(self,
                 initial_soc=StorageSettings.MIN_ALLOWED_SOC,
                 initial_energy_origin=ESSEnergyOrigin.EXTERNAL,
                 capacity=StorageSettings.CAPACITY,
                 max_abs_battery_power_kW=StorageSettings.MAX_ABS_POWER,
                 loss_per_hour=0.01,
                 min_allowed_soc=StorageSettings.MIN_ALLOWED_SOC):

        initial_capacity_kWh = capacity * initial_soc / 100

        self.min_allowed_soc_ratio = min_allowed_soc / 100

        self.capacity = capacity
        self.loss_per_hour = loss_per_hour
        self.max_abs_battery_power_kW = max_abs_battery_power_kW

        # storage capacity, that is already sold:
        self.pledged_sell_kWh = \
            {slot: 0. for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
        # storage capacity, that has been offered (but not traded yet):
        self.offered_sell_kWh = \
            {slot: 0. for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
        # energy, that has been bought:
        self.pledged_buy_kWh = \
            {slot: 0. for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
        # energy, that the storage wants to buy (but not traded yet):
        self.offered_buy_kWh = \
            {slot: 0. for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
        self.time_series_ess_share = \
            {slot: {ESSEnergyOrigin.UNKNOWN: 0.,
                    ESSEnergyOrigin.LOCAL: 0.,
                    ESSEnergyOrigin.EXTERNAL: 0.}
             for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]

        self.charge_history = \
            {slot: '-' for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
        self.charge_history_kWh = \
            {slot: '-' for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
        self.offered_history = \
            {slot: '-' for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
        self.used_history = \
            {slot: '-' for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
        self.energy_to_buy_dict = {
            slot: 0.
            for slot in generate_market_slot_list()
        }

        self._used_storage = initial_capacity_kWh
        self._battery_energy_per_slot = 0.0
        self._used_storage_share = [
            EnergyOrigin(initial_energy_origin, initial_capacity_kWh)
        ]
Exemplo n.º 4
0
 def __call__(self, area):
     self.time_slots = generate_market_slot_list(area)
     # Resetting traded energy before repopulating it
     self.traded_energy_current = {}
     self._populate_area_children_data(area)
     self.traded_energy_current = self._round_energy_trade_profile(
         self.traded_energy_current)
Exemplo n.º 5
0
 def _set_alternative_pricing_scheme(self):
     if ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME != 0:
         for time_slot in generate_market_slot_list():
             final_rate = self.area.config.market_maker_rate[time_slot]
             self.bid_update.reassign_mixin_arguments(time_slot,
                                                      initial_rate=0,
                                                      final_rate=final_rate)
Exemplo n.º 6
0
 def assign_energy_requirement(self, avg_power_W):
     self.energy_per_slot_Wh = (avg_power_W /
                                (duration(hours=1) / self.area.config.slot_length))
     for slot_time in generate_market_slot_list(area=self.area):
         if self._allowed_operating_hours(slot_time) and slot_time >= self.area.now:
             self.energy_requirement_Wh[slot_time] = self.energy_per_slot_Wh
             self.state.desired_energy_Wh[slot_time] = self.energy_per_slot_Wh
Exemplo n.º 7
0
    def produced_energy_forecast_kWh(self):
        """
        Returns flat PV production curve.
        """

        for slot_time in generate_market_slot_list(area=self.area):
            self.energy_production_forecast_kWh[slot_time] = 100
Exemplo n.º 8
0
    def _plot_ess_energy_trace(self, energy: dict, subdir: str,
                               root_name: str):
        """
        Plots ess energy trace for each knot in the hierarchy
        """

        data = list()
        barmode = "stack"
        title = 'ESS ENERGY SHARE ({})'.format(root_name)
        xtitle = 'Time'
        ytitle = 'Energy [kWh]'

        temp = {
            ESSEnergyOrigin.UNKNOWN:
            {slot: 0.
             for slot in generate_market_slot_list()},
            ESSEnergyOrigin.LOCAL:
            {slot: 0.
             for slot in generate_market_slot_list()},
            ESSEnergyOrigin.EXTERNAL:
            {slot: 0.
             for slot in generate_market_slot_list()}
        }

        for time, energy_info in energy.items():
            temp[ESSEnergyOrigin.EXTERNAL][time] = energy_info[
                ESSEnergyOrigin.EXTERNAL]
            temp[ESSEnergyOrigin.LOCAL][time] = energy_info[
                ESSEnergyOrigin.LOCAL]
            temp[ESSEnergyOrigin.UNKNOWN][time] = energy_info[
                ESSEnergyOrigin.UNKNOWN]
        for energy_type in [
                ESSEnergyOrigin.EXTERNAL, ESSEnergyOrigin.LOCAL,
                ESSEnergyOrigin.UNKNOWN
        ]:
            data_obj = go.Bar(x=list(temp[energy_type].keys()),
                              y=list(temp[energy_type].values()),
                              name=f"{energy_type}")
            data.append(data_obj)
        if len(data) == 0:
            return
        plot_dir = os.path.join(self.plot_dir, subdir)
        mkdir_from_str(plot_dir)
        output_file = os.path.join(
            plot_dir, 'ess_energy_share_{}.html'.format(root_name))
        PlotlyGraph.plot_bar_graph(barmode, title, xtitle, ytitle, data,
                                   output_file)
Exemplo n.º 9
0
 def _validate_rates(self):
     for time_slot in generate_market_slot_list():
         rate_change = None if self.fit_to_limit else \
             self.bid_update.energy_rate_change_per_update[time_slot]
         validate_load_device_price(
             initial_buying_rate=self.bid_update.initial_rate[time_slot],
             energy_rate_increase_per_update=rate_change,
             final_buying_rate=self.bid_update.final_rate[time_slot],
             fit_to_limit=self.bid_update.fit_to_limit)
Exemplo n.º 10
0
def copy_profile_to_multiple_days(profile):
    daytime_dict = dict((time_str(time.hour, time.minute), time) for time in profile.keys())
    for slot_time in generate_market_slot_list():
        if slot_time not in profile.keys():
            time_key = time_str(slot_time.hour, slot_time.minute)
            if time_key in daytime_dict:
                profile[slot_time] = profile[daytime_dict[time_key]]

    return profile
Exemplo n.º 11
0
 def _set_or_update_energy_rate_change_per_update(self):
     energy_rate_change_per_update = {}
     for slot in generate_market_slot_list():
         if self.fit_to_limit:
             energy_rate_change_per_update[slot] = \
                 (self.initial_rate[slot] - self.final_rate[slot]) / \
                 self.number_of_available_updates
         else:
             energy_rate_change_per_update[slot] = self.energy_rate_change_per_update[slot]
     self.energy_rate_change_per_update = energy_rate_change_per_update
Exemplo n.º 12
0
    def read_config_event(self):
        self._power_profile_index = self.cloud_coverage \
            if self.cloud_coverage is not None else self.area.config.cloud_coverage
        data = self._read_predefined_profile_for_pv()

        for slot_time in generate_market_slot_list(area=self.area):
            self.energy_production_forecast_kWh[slot_time] = \
                data[slot_time] * self.panel_count
            self.state.available_energy_kWh[slot_time] = \
                self.energy_production_forecast_kWh[slot_time]
Exemplo n.º 13
0
    def __init__(
            self,
            panel_count: int = 1,
            initial_selling_rate: float = ConstSettings.GeneralSettings.
        DEFAULT_MARKET_MAKER_RATE,
            final_selling_rate: float = ConstSettings.PVSettings.
        FINAL_SELLING_RATE,
            fit_to_limit: bool = True,
            update_interval=duration(
                minutes=ConstSettings.GeneralSettings.DEFAULT_UPDATE_INTERVAL),
            energy_rate_decrease_per_update: float = ConstSettings.
        GeneralSettings.ENERGY_RATE_DECREASE_PER_UPDATE,
            max_panel_power_W: float = None,
            use_market_maker_rate: bool = False):
        """
        :param panel_count: Number of solar panels for this PV plant
        :param initial_selling_rate: Upper Threshold for PV offers
        :param final_selling_rate: Lower Threshold for PV offers
        :param fit_to_limit: Linear curve following initial_selling_rate & initial_selling_rate
        :param update_interval: Interval after which PV will update its offer
        :param energy_rate_decrease_per_update: Slope of PV Offer change per update
        :param max_panel_power_W:
        """

        # If use_market_maker_rate is true, overwrite initial_selling_rate to market maker rate
        if use_market_maker_rate:
            initial_selling_rate = GlobalConfig.market_maker_rate

        try:
            validate_pv_device(panel_count=panel_count,
                               max_panel_power_W=max_panel_power_W)
        except D3ADeviceException as e:
            raise D3ADeviceException(str(e))

        if isinstance(update_interval, int):
            update_interval = duration(minutes=update_interval)

        BaseStrategy.__init__(self)
        self.offer_update = UpdateFrequencyMixin(
            initial_selling_rate, final_selling_rate, fit_to_limit,
            energy_rate_decrease_per_update, update_interval)
        for time_slot in generate_market_slot_list():
            try:
                validate_pv_device(
                    initial_selling_rate=self.offer_update.
                    initial_rate[time_slot],
                    final_selling_rate=self.offer_update.final_rate[time_slot])
            except D3ADeviceException as e:
                raise D3ADeviceException(str(e))
        self.panel_count = panel_count
        self.final_selling_rate = final_selling_rate
        self.max_panel_power_W = max_panel_power_W
        self.energy_production_forecast_kWh = {}  # type: Dict[Time, float]
        self.state = PVState()
Exemplo n.º 14
0
    def event_activate(self):
        self.energy_per_slot_Wh = (self.avg_power_W /
                                   (duration(hours=1) / self.area.config.slot_length))

        self._simulation_start_timestamp = self.area.now
        self.hrs_per_day = {day: self._initial_hrs_per_day
                            for day in range(self.area.config.duration.days + 1)}

        for slot_time in generate_market_slot_list(self.area):
            if self._allowed_operating_hours(slot_time):
                self.energy_requirement_Wh[slot_time] = self.energy_per_slot_Wh
                self.state.desired_energy_Wh[slot_time] = self.energy_per_slot_Wh
Exemplo n.º 15
0
 def _update_energy_requirement(self):
     """
     Update required energy values for each market slot.
     :return: None
     """
     self._simulation_start_timestamp = self.area.now
     self.hrs_per_day = {day: self._initial_hrs_per_day
                         for day in range(self.area.config.sim_duration.days + 1)}
     for slot_time in generate_market_slot_list(area=self.area):
         if self._allowed_operating_hours(slot_time.hour):
             self.energy_requirement_Wh[slot_time] = self.load_profile[slot_time] * 1000
             self.state.desired_energy_Wh[slot_time] = self.load_profile[slot_time] * 1000
             self.state.total_energy_demanded_wh += self.load_profile[slot_time] * 1000
Exemplo n.º 16
0
 def produced_energy_forecast_kWh(self):
     # This forecast ist based on the real PV system data provided by enphase
     # They can be found in the tools folder
     # A fit of a gaussian function to those data results in a formula Energy(time)
     for slot_time in generate_market_slot_list(self.area):
         difference_to_midnight_in_minutes = \
             slot_time.diff(self.midnight).in_minutes() % (60 * 24)
         self.energy_production_forecast_kWh[slot_time] = \
             self.gaussian_energy_forecast_kWh(
                 difference_to_midnight_in_minutes) * self.panel_count
         self.state.available_energy_kWh[slot_time] = \
             self.energy_production_forecast_kWh[slot_time]
         assert self.energy_production_forecast_kWh[slot_time] >= 0.0
Exemplo n.º 17
0
 def _validate_rates(self):
     for time_slot in generate_market_slot_list():
         bid_rate_change = None if self.bid_update.fit_to_limit else \
             self.bid_update.energy_rate_change_per_update[time_slot]
         offer_rate_change = None if self.offer_update.fit_to_limit else \
             self.offer_update.energy_rate_change_per_update[time_slot]
         validate_storage_device(
             initial_selling_rate=self.offer_update.initial_rate[time_slot],
             final_selling_rate=self.offer_update.final_rate[time_slot],
             initial_buying_rate=self.bid_update.initial_rate[time_slot],
             final_buying_rate=self.bid_update.final_rate[time_slot],
             energy_rate_increase_per_update=bid_rate_change,
             energy_rate_decrease_per_update=offer_rate_change,
             fit_to_limit=self.bid_update.fit_to_limit,
             update_interval=self.bid_update.update_interval)
Exemplo n.º 18
0
    def event_activate(self):
        """
        Runs on activate event. Reads the power profile data and calculates the required energy
        for each slot.
        :return: None
        """
        # TODO: Need to have 2-stage initialization as well, because the area objects are not
        # created when the constructor is executed if we inherit from a mixin class,
        # therefore config cannot be read at that point
        data = self._read_predefined_profile_for_pv()

        for slot_time in generate_market_slot_list(self.area):
            self.energy_production_forecast_kWh[slot_time] = \
                data[slot_time.format(PENDULUM_TIME_FORMAT)] * self.panel_count
            self.state.available_energy_kWh[slot_time] = \
                self.energy_production_forecast_kWh[slot_time]

        # TODO: A bit clumsy, but this decrease price calculation needs to be added here as well
        # Need to refactor once we convert the config object to a singleton that is shared globally
        # in the simulation
        self._decrease_price_every_nr_s = \
            (self.area.config.tick_length.seconds *
             ConstSettings.GeneralSettings.MAX_OFFER_TRAVERSAL_LENGTH + 1)
Exemplo n.º 19
0
 def __call__(self, area):
     self.time_slots = generate_market_slot_list(area)
     self._populate_area_children_data(area)
Exemplo n.º 20
0
 def __init__(self):
     self.available_energy_kWh = \
         {slot: 0. for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
Exemplo n.º 21
0
 def __init__(self):
     self.desired_energy_Wh = \
         {slot: 0. for slot in generate_market_slot_list()}  # type: Dict[DateTime, float]
     self.total_energy_demanded_wh = 0
Exemplo n.º 22
0
    def update_sold_bought_energy(self, area: Area):
        if ConstSettings.GeneralSettings.KEEP_PAST_MARKETS:
            self.traded_energy[area.uuid] = \
                self._calculate_devices_sold_bought_energy_past_markets(area, area.past_markets)
            self.traded_energy[area.name] = self.traded_energy[area.uuid]
            self.balancing_traded_energy[area.name] = \
                self._calculate_devices_sold_bought_energy_past_markets(
                    area, area.past_balancing_markets)

            self.traded_energy_profile[area.slug] = \
                self._serialize_traded_energy_lists(self.traded_energy, area.uuid)
        else:

            # Calculates current market traded energy
            if area.uuid not in self.traded_energy_current:
                self.traded_energy_current[area.uuid] = {
                    "sold_energy": {},
                    "bought_energy": {}
                }
            if area.current_market is not None:
                self.time_slots = [area.current_market.time_slot]
                self._calculate_devices_sold_bought_energy(
                    self.traded_energy_current[area.uuid], area.current_market)
                self.traded_energy_current[
                    area.uuid] = self._serialize_traded_energy_lists(
                        self.traded_energy_current, area.uuid)
                self.time_slots = generate_market_slot_list(area)

                # Merges traded energy for the CSV file
                # TODO: Adapt to not store the full results on D3A.
                if area.slug not in self.traded_energy_profile:
                    self.traded_energy_profile[area.slug] = \
                        {"sold_energy": {}, "bought_energy": {}}
                    self._calculate_devices_sold_bought_energy(
                        self.traded_energy_profile[area.slug],
                        area.current_market)
                    self.traded_energy_profile[
                        area.slug] = self._serialize_traded_energy_lists(
                            self.traded_energy_profile, area.slug)
                else:
                    traded_energy_current_name = {
                        area.slug: self.traded_energy_current[area.uuid]
                    }
                    self.traded_energy_profile = merge_energy_trade_profile_to_global(
                        traded_energy_current_name, self.traded_energy_profile,
                        generate_market_slot_list(area))

            if self._should_export_plots:
                # Traded energy for plot
                if area.uuid not in self.traded_energy:
                    self.traded_energy[area.uuid] = {
                        "sold_energy": {},
                        "bought_energy": {}
                    }
                self._calculate_devices_sold_bought_energy(
                    self.traded_energy[area.uuid], area.current_market)
                self.traded_energy[area.name] = self.traded_energy[area.uuid]
                if area.name not in self.balancing_traded_energy:
                    self.balancing_traded_energy[area.name] = {
                        "sold_energy": {},
                        "bought_energy": {}
                    }
                if len(area.past_balancing_markets) > 0:
                    self._calculate_devices_sold_bought_energy(
                        self.balancing_traded_energy[area.name],
                        area.current_balancing_market)

                self.balancing_traded_energy[
                    area.uuid] = self.balancing_traded_energy[area.name]
Exemplo n.º 23
0
    def __init__(
        self,
        initial_soc: float = StorageSettings.MIN_ALLOWED_SOC,
        min_allowed_soc=StorageSettings.MIN_ALLOWED_SOC,
        battery_capacity_kWh: float = StorageSettings.CAPACITY,
        max_abs_battery_power_kW: float = StorageSettings.MAX_ABS_POWER,
        cap_price_strategy: bool = False,
        initial_selling_rate: Union[
            float, dict] = StorageSettings.SELLING_RATE_RANGE.initial,
        final_selling_rate: Union[
            float, dict] = StorageSettings.SELLING_RATE_RANGE.final,
        initial_buying_rate: Union[
            float, dict] = StorageSettings.BUYING_RATE_RANGE.initial,
        final_buying_rate: Union[
            float, dict] = StorageSettings.BUYING_RATE_RANGE.final,
        loss_per_hour=StorageSettings.LOSS_PER_HOUR,
        loss_function=StorageSettings.LOSS_FUNCTION,
        fit_to_limit=True,
        energy_rate_increase_per_update=None,
        energy_rate_decrease_per_update=None,
        update_interval=None,
        initial_energy_origin: Enum = ESSEnergyOrigin.EXTERNAL,
        balancing_energy_ratio: tuple = (
            BalancingSettings.OFFER_DEMAND_RATIO,
            BalancingSettings.OFFER_SUPPLY_RATIO)):

        if update_interval is None:
            update_interval = \
                duration(minutes=ConstSettings.GeneralSettings.DEFAULT_UPDATE_INTERVAL)

        if min_allowed_soc is None:
            min_allowed_soc = StorageSettings.MIN_ALLOWED_SOC
        self.initial_soc = initial_soc

        validate_storage_device(
            initial_soc=initial_soc,
            min_allowed_soc=min_allowed_soc,
            battery_capacity_kWh=battery_capacity_kWh,
            max_abs_battery_power_kW=max_abs_battery_power_kW,
            loss_per_hour=loss_per_hour,
            loss_function=loss_function,
            fit_to_limit=fit_to_limit,
            energy_rate_increase_per_update=energy_rate_increase_per_update,
            energy_rate_decrease_per_update=energy_rate_decrease_per_update)

        if isinstance(update_interval, int):
            update_interval = duration(minutes=update_interval)

        BidEnabledStrategy.__init__(self)

        self.offer_update = \
            UpdateFrequencyMixin(initial_rate=initial_selling_rate,
                                 final_rate=final_selling_rate,
                                 fit_to_limit=fit_to_limit,
                                 energy_rate_change_per_update=energy_rate_decrease_per_update,
                                 update_interval=update_interval)
        for time_slot in generate_market_slot_list():
            validate_storage_device(
                initial_selling_rate=self.offer_update.initial_rate[time_slot],
                final_selling_rate=self.offer_update.final_rate[time_slot])
        self.bid_update = \
            UpdateFrequencyMixin(
                initial_rate=initial_buying_rate,
                final_rate=final_buying_rate,
                fit_to_limit=fit_to_limit,
                energy_rate_change_per_update=energy_rate_increase_per_update,
                update_interval=update_interval,
                rate_limit_object=min
            )
        for time_slot in generate_market_slot_list():
            validate_storage_device(
                initial_buying_rate=self.bid_update.initial_rate[time_slot],
                final_buying_rate=self.bid_update.final_rate[time_slot])
        self.state = \
            StorageState(initial_soc=initial_soc,
                         initial_energy_origin=initial_energy_origin,
                         capacity=battery_capacity_kWh,
                         max_abs_battery_power_kW=max_abs_battery_power_kW,
                         loss_per_hour=loss_per_hour,
                         loss_function=loss_function,
                         min_allowed_soc=min_allowed_soc)
        self.cap_price_strategy = cap_price_strategy
        self.balancing_energy_ratio = BalancingRatio(*balancing_energy_ratio)
Exemplo n.º 24
0
Arquivo: pv.py Projeto: xg86/d3a
 def _validate_rates(self):
     for time_slot in generate_market_slot_list():
         validate_pv_device_price(
             initial_selling_rate=self.offer_update.initial_rate[time_slot],
             final_selling_rate=self.offer_update.final_rate[time_slot])
Exemplo n.º 25
0
 def __init__(self):
     self.available_energy_kWh = \
         {slot: 0. for slot in generate_market_slot_list()}
Exemplo n.º 26
0
    def __init__(
            self,
            avg_power_W,
            hrs_per_day=None,
            hrs_of_day=None,
            fit_to_limit=True,
            energy_rate_increase_per_update=1,
            update_interval=duration(
                minutes=ConstSettings.GeneralSettings.DEFAULT_UPDATE_INTERVAL),
            initial_buying_rate: Union[
                float, dict,
                str] = ConstSettings.LoadSettings.INITIAL_BUYING_RATE,
            final_buying_rate: Union[
                float, dict,
                str] = ConstSettings.LoadSettings.FINAL_BUYING_RATE,
            balancing_energy_ratio: tuple = (
                ConstSettings.BalancingSettings.OFFER_DEMAND_RATIO,
                ConstSettings.BalancingSettings.OFFER_SUPPLY_RATIO),
            use_market_maker_rate: bool = False):
        """
        Constructor of LoadHoursStrategy
        :param avg_power_W: Power rating of load device
        :param hrs_per_day: Daily energy usage
        :param hrs_of_day: hours of day energy is needed
        :param fit_to_limit: if set to True, it will make a linear curve
        following following initial_buying_rate & final_buying_rate
        :param energy_rate_increase_per_update: Slope of Load bids change per update
        :param update_interval: Interval after which Load will update its offer
        :param initial_buying_rate: Starting point of load's preferred buying rate
        :param final_buying_rate: Ending point of load's preferred buying rate
        :param use_market_maker_rate: If set to True, Load would track its final buying rate
        as per utility's trading rate
        """

        # If use_market_maker_rate is true, overwrite final_buying_rate to market maker rate
        if use_market_maker_rate:
            final_buying_rate = GlobalConfig.market_maker_rate

        if isinstance(update_interval, int):
            update_interval = duration(minutes=update_interval)

        BidEnabledStrategy.__init__(self)
        self.bid_update = \
            UpdateFrequencyMixin(initial_rate=initial_buying_rate,
                                 final_rate=final_buying_rate,
                                 fit_to_limit=fit_to_limit,
                                 energy_rate_change_per_update=energy_rate_increase_per_update,
                                 update_interval=update_interval, rate_limit_object=min)
        try:
            validate_load_device(avg_power_W=avg_power_W,
                                 hrs_per_day=hrs_per_day,
                                 hrs_of_day=hrs_of_day)
        except D3ADeviceException as e:
            raise D3ADeviceException(str(e))

        for time_slot in generate_market_slot_list():
            rate_change = self.bid_update.energy_rate_change_per_update[
                time_slot]
            try:
                validate_load_device(
                    initial_buying_rate=self.bid_update.
                    initial_rate[time_slot],
                    final_buying_rate=self.bid_update.final_rate[time_slot],
                    energy_rate_increase_per_update=rate_change)
            except D3ADeviceException as e:
                raise D3ADeviceException(str(e))
        self.state = LoadState()
        self.avg_power_W = avg_power_W

        # consolidated_cycle is KWh energy consumed for the entire year
        self.daily_energy_required = None
        # Energy consumed during the day ideally should not exceed daily_energy_required
        self.energy_per_slot_Wh = None
        self.energy_requirement_Wh = {}  # type: Dict[Time, float]
        self.hrs_per_day = {}  # type: Dict[int, int]

        self.assign_hours_of_per_day(hrs_of_day, hrs_per_day)
        self.balancing_energy_ratio = BalancingRatio(*balancing_energy_ratio)
Exemplo n.º 27
0
 def __init__(self):
     self.desired_energy_Wh = \
         {slot: 0. for slot in generate_market_slot_list()}
     self.total_energy_demanded_wh = 0