예제 #1
0
    def run_rolling_window(self, rolling_interval, rolling_step, system=None, optimizer=None,):
        self.logger.info('Running simulation.')

        if system is not None and self.system is None:
            self.system = system
        else:
            ValueError('Error assigning system to the simulation.')

        if optimizer is not None and self.optimizer is None:
            self.optimizer = optimizer
        else:
            ValueError('Error assigning optimizer to the simulation.')

        if self.system is None:
            raise ValueError('A system is required.')

        if self.optimizer is None:
            raise ValueError('An optimizer is required.')

        rolling_step = timestep_conversion(rolling_step, pd_units=True)
        time_range = pandas.date_range(start=rolling_interval[0], end=rolling_interval[1], freq=rolling_step)

        for step in time_range:
            self.run_single_step(current_time=step)
            self.system.clear()
            self.optimizer.clear()
            self.clear()
예제 #2
0
    def test_timestep_to_seconds(self):
        with self.assertRaises(ValueError):
            timestep_conversion('1s', std_units=True, pd_units=False)
        with self.assertRaises(ValueError):
            timestep_conversion('10h', std_units=False, pd_units=True)

        case = [
            ('1H', 3600),
            ('1h', 3600),
            ('1T', 60),
            ('1m', 60),
            ('15min', 15 * 60),
            ('15T', 15 * 60),
            ('15m', 15 * 60),
            ('100s', 100),
            ('100S', 100),
        ]

        for case_input, case_output in case:
            self.assertEqual(timestep_to_seconds(case_input), case_output)
예제 #3
0
def synthetic_solar_irradiance(
        time_interval, panel_tilt, panel_orientation, latitude, longitude, timestep='1h', unit='kW', utc_localize=False
):
    """Creates synthetic solar radiation data for a location and panel geometry.
    """
    ground_vector = (0.0, 0.0, 1.0)  # (x, y, z) length = 1
    panel_vector = polar2cart(1.0, polar_angle=90.0 - panel_tilt, azimuthal_angle=panel_orientation)

    time_interval = check_time_interval(time_interval, last_step_included=False, delta_step=timestep)

    if unit == 'kW' or unit == 'kw':
        scaler = 1000  # Converts to kW
    else:
        scaler = 1

    # The pysolar module requires localized data
    start_datetime = pytz.utc.localize(time_interval[0])
    end_datetime = pytz.utc.localize(time_interval[1])

    date_range = pandas.date_range(
        start=start_datetime, end=end_datetime, freq=timestep_conversion(timestep, pd_units=True)
    )

    dates, radiations = list(), list()

    for time in date_range:
        azimuth, altitude_deg = pysolar.solar.get_position(latitude, longitude, time)
        sun_vector = polar2cart(1, polar_angle=90.0 - altitude_deg, azimuthal_angle=azimuth)

        if altitude_deg <= 0:
            horizontal_radiation = 0.
        else:
            horizontal_radiation = pysolar.radiation.get_radiation_direct(time, altitude_deg) / scaler

        perpendicular_radiation = horizontal_radiation / cos(angle_between(sun_vector, ground_vector))
        tilted_radiatiation = perpendicular_radiation * cos(angle_between(sun_vector, panel_vector))

        radiations.append(tilted_radiatiation)

    radiation_results = pandas.DataFrame({'pysolar_radiation': radiations}, index=date_range)

    if not utc_localize:
        radiation_results.index = radiation_results.index.tz_convert(None)

    return radiation_results
예제 #4
0
파일: ioapis.py 프로젝트: covrig/pyems
def get_spanish_electricity_prices(
        time_interval, timestep, tariff='tariff_2.0A', token=None, utc_interval=True, last_included=False
):

    time_interval = check_time_interval(time_interval, str_format=Parameter.UTC_DATETIME_FORMAT)
    hour_step = '1h'

    if timestep != hour_step:

        timestep = timestep_conversion(timestep, pd_units=True)
        hourly_interval = time_interval.copy()

        if time_interval[0].time() > datetime.time(time_interval[0].hour):
            hourly_interval[0] = time_interval[0].replace(minute=0, second=0, microsecond=0)

        if time_interval[1].time() > datetime.time(time_interval[1].hour):
            hourly_interval[1] = time_interval[1].replace(minute=0, second=0, microsecond=0) + datetime.timedelta(
                hours=1)

        prices = get_hourly_spanish_electricity_prices(
            time_interval=hourly_interval, utc_interval=utc_interval, token=token, tariff=tariff,
            last_included=last_included
        )
        prices = prices.to_frame('prices')  # Convert pandas.Series to pandas.DataFrame
        prices = series_upsampling(
            prices, new_time_interval=time_interval, new_timestep=timestep, old_timestep=hour_step,
            upsample_values=False
        )

    else:
        prices = get_hourly_spanish_electricity_prices(
            time_interval=time_interval, utc_interval=utc_interval, token=token, tariff=tariff,
            last_included=last_included
        )

    return prices
예제 #5
0
    def extract_results_from_opt_model(self, config):

        self.logger.info('Extracting results from optimization model.')

        # Extract variables of interest from the model

        raw_results = {}
        for e in self.optimization_model.E_set:
            raw_results[e] = numpy.array([
                self.optimization_model.E[e][t].value
                for t in self.optimization_model.periods
            ])

        if self.system.has_battery:
            raw_results['soc'] = numpy.array([
                self.optimization_model.soc[t].value
                for t in self.optimization_model.periods
            ])

        # check_soc = numpy.array([self.optimization_model.soc[t].value for t in range(len(self.optimization_model.soc))])
        # print(f'Full SOC vector: {check_soc}')

        # Check the raw_results for undefined values in the solver output

        for key, values in raw_results.items():
            if None in values:
                raise ValueError(
                    'The solver was unable to find a solution for \
                                 some variables in at least: {}'.format(key))

        # Combine var also checks that the system do not charge and discharge or
        # buy and sell energy at the same time. Below are the error messages:

        results = {}

        if not (self.system.has_interruptable_loads
                or self.system.has_schedulable_loads):
            results['building_load'] = self.system.fix_electrical_load
        else:
            raise NotImplementedError('Flexible loads not implemented yet.')

        if self.system.has_stochastic_generators:
            results[
                'stochastic_generation'] = self.system.stochastic_electrical_gen.copy(
                )

        if self.system.has_external_grid:
            error_supply = 'Invalid solution. The system buys and sells \
                            electricity at the same time'

            results['power_supply_flow'] = combine_positive_negative_variables(
                raw_results['buy'], raw_results['sell'], error_supply)

        if self.system.has_battery:
            error_batt = 'Invalid solution. The system is charging and \
                         discharging the battery at the same time'

            results[
                'battery_energy_flow'] = combine_positive_negative_variables(
                    raw_results['batt_dis'], raw_results['batt_chrg'],
                    error_batt)
            results['battery_soc'] = numpy.array(raw_results['soc'])

        if self.system.has_external_grid:
            results['prices_buy'] = numpy.array(
                self.optimization_model.prices['buy'])
            results['prices_sell'] = numpy.array(
                self.optimization_model.prices['sell'])

        timestep = timestep_conversion(config['timestep'], pd_units=True)
        results_index = pandas.date_range(start=config['start'],
                                          periods=config['periods'],
                                          freq=timestep)

        self.results = pandas.DataFrame(results, index=results_index)

        # We assume that the first SOC <results_index[0]> in the results is the initial SOC. Therefore, the target SOC
        # for the next period is the second one <results_index[1]>
        self.target_soc = float(self.results.at[results_index[1],
                                                'battery_soc'])

        return results
예제 #6
0
파일: prophet.py 프로젝트: covrig/pyems
    def forecast(self, forecast_interval, input_data, target_label, timestep):

        forecast_interval = check_time_interval(forecast_interval)

        try:
            input_data.index = input_data.index.tz_convert(None)
        except TypeError:
            pass

        columns = list(input_data.columns)
        columns.remove(target_label)

        if len(columns) > 0:
            self.logger.info(
                f'Using regressors: {columns}, in FB Prophet model.')

        input_data.interpolate(inplace=True)

        training_data = input_data[
            input_data.index < forecast_interval[0]].copy()
        test_data = input_data[input_data.index >= forecast_interval[0]].copy()

        training_data[self.raw_index_label] = training_data.index.strftime(
            self.datetime_format)
        training_data.reset_index(inplace=True, drop=True)
        rename_columns = {
            self.raw_index_label: self.ph_index,
            target_label: self.raw_target_label
        }
        training_data.rename(index=str, columns=rename_columns, inplace=True)

        model = Prophet()
        for column in columns:
            model.add_regressor(column)

        self.logger.info('Training FB Prophet model.')

        with suppress_stdout_stderr():
            model.fit(training_data)

        if test_data.empty:
            timestep = timestep_conversion(timestep, pd_units=True)
            future = pd.date_range(start=forecast_interval[0],
                                   end=forecast_interval[1],
                                   freq=timestep).values
            test_data = pd.DataFrame({self.ph_index: future})
        else:
            test_data[self.raw_index_label] = test_data.index.strftime(
                self.datetime_format)
            test_data.reset_index(inplace=True, drop=True)
            rename_columns = {
                self.raw_index_label: self.ph_index,
                target_label: self.raw_target_label
            }
            test_data.rename(index=str, columns=rename_columns, inplace=True)
            test_data.drop(columns=[self.raw_target_label], inplace=True)

        self.logger.info('Producing FB Prophet forecast.')

        forecast_table = model.predict(test_data)
        forecast_table.set_index(self.ph_index, drop=True, inplace=True)
        forecast_table.index = pd.to_datetime(forecast_table.index,
                                              format=self.datetime_format,
                                              utc=True)

        forecast = forecast_table.loc[:, [self.y_hat]]
        forecast.rename(columns={self.y_hat: target_label}, inplace=True)
        forecast.index.rename(self.raw_index_label, inplace=True)

        return forecast
예제 #7
0
    def test_timestep_conversion(self):
        with self.assertRaises(ValueError):
            timestep_conversion('1h', std_units=True, pd_units=True)
        with self.assertRaises(ValueError):
            timestep_conversion('2h', std_units=True, pd_units=False)
        with self.assertRaises(ValueError):
            timestep_conversion('2h', std_units=False, pd_units=False)
        with self.assertRaises(ValueError):
            timestep_conversion('2s', std_units=True, pd_units=False)
        with self.assertRaises(ValueError):
            timestep_conversion('2s', std_units=False, pd_units=True)

        case_std = [
            ('1H', '1h'),
            ('1h', '1h'),
            ('1T', '1m'),
            ('1m', '1m'),
            ('15min', '15m'),
            ('15T', '15m'),
            ('15m', '15m'),
            ('100s', '100s'),
            ('100S', '100s'),
        ]

        case_pd = [
            ('1H', '1H'),
            ('1h', '1H'),
            ('1T', '1T'),
            ('1m', '1T'),
            ('15min', '15min'),
            ('15T', '15T'),
            ('15m', '15T'),
            ('100s', '100S'),
            ('100S', '100S'),
        ]

        for case_input, case_output in case_std:
            self.assertEqual(timestep_conversion(case_input, std_units=True),
                             case_output)

        for case_input, case_output in case_pd:
            self.assertEqual(timestep_conversion(case_input, pd_units=True),
                             case_output)
예제 #8
0
    def run_single_step(
            self, system=None, optimizer=None, current_time=None, simulation_end='prices_availability',
            midnight_ahead=None, simulation_length=None
    ):
        self.logger.info('Running simulation.')

        if system is not None and self.system is None:
            self.system = system
        else:
            ValueError('Error assigning system to the simulation.')

        if optimizer is not None and self.optimizer is None:
            self.optimizer = optimizer
        else:
            ValueError('Error assigning optimizer to the simulation.')

        if current_time is not None:
            self.current_time = current_time
        else:
            self.current_time = get_current_time()  # Utc time

        self.start = find_next_step_start(current_time=self.current_time, timestep=self.timestep)
        # i.e. assume current_time=13:23, and timestep=5m, next start would be 13:25

        if simulation_end == 'fix':
            self.end = get_fix_simulation_length_end_timestamp(self.start, simulation_length=simulation_length)
        elif simulation_end == 'prices_availability':
            if self.system.has_external_grid:

                """Assume we are at day D and we want to run the simulation, at least, for the remaining of day D."
                The next day is D+1. We want the prices of the remaining of the D plus, if available, the prices of day D+1. 
                Therefore, we'll need the utc time corresponding to 
                the midnight between day D and D+1 or between D+1 and D+2 (depending on prices availability).
                """
                publication_time = self.system.get_external_grid_object().publication_time
                local_current_datetime = utc_to_local(self.current_time, local_tz=self.local_tz)
                midnight_ahead = 1 if local_current_datetime.time() >= publication_time else 0  # 0 is D-D+1 midnight
                self.end = get_following_midnight_utc_timestamp(
                    self.current_time, local_tz=self.local_tz, midnight_ahead=midnight_ahead
                )
            else:
                message = (
                    f'The Simulation object cannot determine the end of the simulation based '
                    f'on prices availability because there is no grid in the system.'
                )
                raise ValueError(message)
        elif simulation_end == 'midnight_ahead':
            self.end = get_following_midnight_utc_timestamp(
                self.current_time, local_tz=self.local_tz, midnight_ahead=midnight_ahead
            )
        else:
            raise ValueError('Invalid method to compute the simulation end.')

        pandas_timestep = timestep_conversion(self.timestep, pd_units=True)
        self.periods = len(pandas.date_range(start=self.start, end=self.end, closed='left', freq=pandas_timestep))
        self.interval = [self.start, self.end]

        time_config = self.get_time_configuration()
        self.system.prepare_to_optimize(config=time_config)
        self.results = self.optimizer.solve(system=self.system, config=time_config)

        return self.results