Пример #1
0
    def __init__(self, constraint_type, limit_type, years_of_analysis,
                 datetime_freq):
        """Initialize a constraint.

        Args:
            constraint_type (str): state of energy, charge, or discharge (not case sensitive)
            limit_type (str): maximum limit or minimum (not case sensitive)
            years_of_analysis (list): list of years that should be included in the returned Index
            datetime_freq (str): the pandas frequency in string representation -- required to create dateTime rang

        """
        self.type = constraint_type.lower()
        self.is_max = limit_type.lower() == 'max'
        self.is_min = limit_type.lower() == 'min'
        if limit_type not in ['max', 'min']:
            raise SyntaxWarning("limit_type can be 'max' or 'min'")

        index = Lib.create_timeseries_index(years_of_analysis, datetime_freq)
        size = len(index)
        self.parents = pd.DataFrame(columns=[
            'DateTime', 'Parent'
        ])  # records which valuestreams have had a non-base value
        self.owner = pd.Series(
            np.repeat('null', size),
            index=index)  # records which valuestream(s) set the current VALUE

        # records the value that would ensure all past updated requirements would also be met
        if self.is_max:
            self.value = pd.Series(np.repeat(VERY_LARGE_NUMBER, size),
                                   index=index)
        if self.is_min:
            self.value = pd.Series(np.zeros(size), index=index)
Пример #2
0
    def calc_retail_energy_price(tariff, freq, analysis_yr, non_zero=True):
        """ transforms tariff data file into time series dataFrame

        Args:
            tariff (DataFrame): raw tariff dataframe.
            freq (str): the frequency of the timeseries data we are working with
            analysis_yr (float): Year for which to build the tariff for

        Returns: a DataFrame with the index beginning at hour 0

        """
        temp = pd.DataFrame(
            index=Lib.create_timeseries_index([analysis_yr], freq))
        size = len(temp)

        # Build Energy Price Vector
        temp['he'] = (temp.index + pd.Timedelta('1s')).hour + 1
        temp.loc[:, 'p_energy'] = np.zeros(shape=size)

        billing_period = [[] for _ in range(size)]

        for p in tariff.index:
            # edit the pricedf energy price and period values for all of the periods defined
            # in the tariff input file
            bill = tariff.loc[p, :]
            mask = Financial.create_bill_period_mask(bill, temp.index.month,
                                                     temp['he'],
                                                     temp.index.weekday)
            if bill['Charge'].lower() == 'energy':
                current_energy_prices = temp.loc[mask, 'p_energy'].values
                if np.any(np.greater(current_energy_prices, 0)):
                    # More than one energy price applies to the same time step
                    TellUser.warning(
                        'More than one energy price applies to the same time step.'
                    )
                # Add energy prices
                temp.loc[mask, 'p_energy'] += bill['Value']
            elif bill['Charge'].lower() == 'demand':
                # record billing period
                for i, true_false in enumerate(mask):
                    if true_false:
                        billing_period[i].append(p)
        billing_period = pd.DataFrame({'billing_period': billing_period},
                                      dtype='object')
        temp.loc[:, 'billing_period'] = billing_period.values

        # ADD CHECK TO MAKE SURE ENERGY PRICES ARE THE SAME FOR EACH OVERLAPPING BILLING PERIOD
        # Check to see that each timestep has a period assigned to it

        if (not billing_period.apply(len).all() or np.any(
                np.equal(temp.loc[:, 'p_energy'].values, 0))) and non_zero:
            TellUser.error(
                'The billing periods in the input file do not partition the year, '
                + 'please check the tariff input file')
            raise TariffError('Please check the retail tariff')
        return temp
Пример #3
0
    def grow_drop_data(self, years, frequency, load_growth):
        """ Adds data by growing the given data OR drops any extra data that might have slipped in.
        Update variable that hold timeseries data after adding growth data. These method should be called after
        add_growth_data and before the optimization is run.

        Args:
            years (List): list of years for which analysis will occur on
            frequency (str): period frequency of the timeseries data
            load_growth (float): percent/ decimal value of the growth rate of loads in this simulation


        """
        data_year = self.price.index.year.unique()
        no_data_year = {pd.Period(year)
                        for year in years} - {
                            pd.Period(year)
                            for year in data_year
                        }  # which years do we not have data for

        if len(no_data_year) > 0:
            for yr in no_data_year:
                source_year = pd.Period(max(data_year))

                years = yr.year - source_year.year

                # Build Energy Price Vector based on the new year
                new_index = Lib.create_timeseries_index([yr.year], frequency)
                temp = pd.DataFrame(index=new_index)
                weekday = (new_index.weekday < SATURDAY).astype('int64')
                he = (new_index + pd.Timedelta('1s')).hour + 1
                temp['price'] = np.zeros(len(new_index))

                for p in range(len(self.tariff)):
                    # edit the pricedf energy price and period values for all of the periods defined
                    # in the tariff input file
                    bill = self.tariff.iloc[p, :]
                    mask = Financial.create_bill_period_mask(
                        bill, temp.index.month, he, weekday)

                    current_energy_prices = temp.loc[mask, 'price'].values
                    if np.any(np.greater(current_energy_prices, 0)):
                        # More than one energy price applies to the same time step
                        TellUser.warning(
                            'More than one energy price applies to the same time step.'
                        )
                    # Add energy prices
                    temp.loc[mask, 'price'] += bill['Value']
                # apply growth to new energy rate
                new_p_energy = temp['price'] * (1 + self.growth)**years
                self.price = pd.concat([self.price, new_p_energy],
                                       sort=True)  # add to existing
Пример #4
0
    def assign_optimization_level(analysis_years, control_horizon,
                                  predictive_horizon, frequency, dt):
        """ creates an index based on the opt_years presented and then

         Args:
            analysis_years (list): List of Period years where we need data for
            control_horizon (str, int): optimization window length from the user
            predictive_horizon (str, int): mcp horizon input from the user
                (if 0, then assume the same as CONTROL_HORIZON)
                should be greater than or equal to CONTROL_HORIZON value
            frequency (str): time step in string form
            dt (float): time step

        Return:
            opt_agg (DataFrame): 1 column, all indexes with the same value will be in one
            optimization problem together

        """
        # create dataframe to fill
        level_index = Lib.create_timeseries_index(analysis_years, frequency)
        level_df = pd.DataFrame({'control': np.zeros(len(level_index))},
                                index=level_index)
        current_control_level = 0
        # control level should not overlap multiple years & there is only one per timestep
        for yr in level_index.year.unique():
            sub = copy.deepcopy(level_df[level_df.index.year == yr])
            if control_horizon == 'year':
                # continue counting from previous year opt_agg
                level_df.loc[level_df.index.year == yr,
                             'control'] = current_control_level + 1
            elif control_horizon == 'month':
                # continue counting from previous year opt_agg
                level_df.loc[
                    level_df.index.year == yr,
                    'control'] = current_control_level + sub.index.month
            else:
                # n is number of hours
                control_horizon = int(control_horizon)
                sub['ind'] = range(len(sub))
                # split year into groups of n days
                ind = (sub.ind // (control_horizon / dt)).astype(int) + 1
                # continue counting from previous year opt_agg
                level_df.loc[level_df.index.year == yr,
                             'control'] = ind + current_control_level
            current_control_level = max(level_df.control)

        # predictive level can overlap multiple years & there can be 1+ per timestep
        if not predictive_horizon:
            # set to be the control horizon
            level_df['predictive'] = level_df.loc[:, 'control']
        else:
            # TODO this has not been tested yet -- HN (sorry hmu and I will help)
            # create a list of lists
            max_index = len(level_df['control'])
            predictive_level = np.repeat([], max_index)
            current_predictive_level_beginning = 0
            current_predictive_level = 0

            for control_level in level_df.control.unique():
                if predictive_horizon == 'year':
                    # needs to be a year from the beginning of the current predictive level, determine
                    # length of the year based on first index in subset
                    start_year = level_index[
                        current_predictive_level_beginning].year[0]
                    f_date = date(start_year, 1, 1)
                    l_date = date(start_year + 1, 1, 1)
                    delta = l_date - f_date
                    current_predictive_level_end = int(delta.days * dt)

                elif predictive_horizon == 'month':
                    # needs to be a month from the beginning of the current predictive level, determine
                    # length of the month based on first index in subset
                    start_index = level_index[
                        current_predictive_level_beginning]
                    current_predictive_level_end = calendar.monthrange(
                        start_index.year, start_index.month)
                else:
                    current_predictive_level_end = predictive_horizon * dt
                # make sure that CURRENT_PREDICTIVE_LEVEL_END stays less than or equal to MAX_INDEX
                current_predictive_level_end = min(
                    current_predictive_level_end, max_index)
                # add CURRENT_PREDICTIVE_LEVEL to lists between CURRENT_PREDICTIVE_LEVEL_BEGINNING and CURRENT_PREDICTIVE_LEVEL_END
                update_levels = predictive_level[
                    current_predictive_level_beginning,
                    current_predictive_level_end]
                update_levels = [
                    dt_level.append(current_predictive_level)
                    for dt_level in update_levels
                ]
                predictive_level[current_predictive_level_beginning,
                                 current_predictive_level_end] = update_levels
                current_predictive_level_beginning = np.sum(
                    level_df.control == control_level)
                # increase CURRENT_PREDICTIVE_LEVEL
                current_predictive_level += 1
            level_df['predictive'] = predictive_level
        return level_df