Exemple #1
0
 def test_change_res_sum_larger_timestep(self):
     input_array = [10, 10, 20, 20]
     output_array = chres.changeResolution(values=input_array,
                                             oldResolution=900,
                                             newResolution=3600,
                                             method="sum")
     assert output_array == [60]
def load_hourly_factors(filename, time_discretization=3600):
    """
    """
    # Initialization
    hourly_factors = {}
    temperature_range = [-15, -10, -5, 0, 5, 10, 15, 20, 25, 100]
    book_hourly = xlrd.open_workbook(filename)
    
    # Iterate over all sheets
    for sheetname in book_hourly.sheet_names():
        sheet = book_hourly.sheet_by_name(sheetname)
        
        temp_factors = {} # Create temporary dictionary for each sheet
        for d in range(7):
            for t in range(len(temperature_range)):
                # Read values
                values = [sheet.cell_value(d*11+t+1, hour+1) 
                          for hour in range(24)]
                if time_discretization != 3600:
                    values = cr.changeResolution(values, 3600, 
                                                 time_discretization, "sum")
                temp_factors[d, temperature_range[t]] = np.array(values)
        
        # Store values
        hourly_factors[sheetname] = temp_factors
    
    # Return final results
    return hourly_factors
Exemple #3
0
 def test_change_res_mean_larger_timestep_2(self):
     input_array = [10, 20, 20, 20, 20, 30]
     output_array = chres.changeResolution(values=input_array,
                                             oldResolution=900,
                                             newResolution=3600,
                                             method="mean")
     assert output_array[0] == 10
     assert output_array[1] == 20
Exemple #4
0
 def test_change_res_sum_smaller_timestep(self):
     input_array = [10, 20]
     output_array = chres.changeResolution(values=input_array,
                                             oldResolution=3600,
                                             newResolution=900,
                                             method="sum")
     assert output_array[0] == 2.5
     assert output_array[1] == 2.5
     assert output_array[2] == 2.5
     assert output_array[3] == 2.5
     assert output_array[4] == 5
     assert output_array[5] == 5
     assert output_array[6] == 5
     assert output_array[7] == 5
Exemple #5
0
    def get_occ_profile_in_curr_timestep(self, timestep=None, int_con=False):
        """
        Returns occupancy profile in current timestep (as occupancy profile
        is saved with 600 seconds timestep, per default)

        Parameters
        ----------
        timestep : int, optional
            Defines specific timestep to return occupancy profile in
            (default: None). If None is chosen, returns profile with
            timestep found in environment.timer
        int_con : bool, optional
            Defines, if output values should be converted into integer
            numbers (conversion might lead to float numbers, depending
            on chosen timesteps) (default: False)

        Returns
        -------
        occ_profile : np.array
            Numpy array holding number of persons, present within
            zone
        """

        occ_profile = copy.copy(self.occupancy)

        if timestep is None:
            timestep = self.environment.timer.timeDiscretization

        occ_profile = chres.changeResolution(values=occ_profile,
                                             oldResolution=600,
                                             newResolution=timestep)

        if int_con:
            for i in range(len(occ_profile)):
                occ_profile[i] = int(round(occ_profile[i]))

        return occ_profile
    def __init__(self,
                 environment,
                 method=0,
                 loadcurve=[],
                 annualDemand=None,
                 profileType="H0",
                 singleFamilyHouse=True,
                 total_nb_occupants=0,
                 randomizeAppliances=True,
                 lightConfiguration=0,
                 occupancy=[],
                 do_normalization=False,
                 method_3_type=None,
                 method_4_type=None,
                 prev_heat_dev=False,
                 app_filename=None,
                 light_filename=None,
                 season_light_mod=False,
                 light_mod_fac=0.25):
        """
        Parameters
        ----------
        environment : Environment object
            Common to all other objects. Includes time and weather instances
        method : Integer, optional
            - `0` : Provide load curve directly (for all timesteps!)
            - `1` : Standard load profile
            - `2` : Stochastic electrical load model (only residential)
            - `3` : Annual profile based on measured weekly profiles
                    (non-residential)
            - `4` : Annual profile based on measured annual profiles
                    (non-residential)
        loadcurve : Array-like, optional
            Load curve for all investigated time steps
        annualDemand : Float (required for SLP and recommended for method 2)
            Annual electrical demand in kWh.
            If method 2 is chosen but no value is given, a standard value for
            Germany (http://www.die-stromsparinitiative.de/fileadmin/bilder/
            Stromspiegel/Brosch%C3%BCre/Stromspiegel2014web_final.pdf) is used.
            (default: None)
        profileType : String (required for SLP; method=1)
            - H0 : Household
            - L0 : Farms
            - L1 : Farms with breeding / cattle
            - L2 : Farms without cattle
            - G0 : Business (general)
            - G1 : Business (workingdays 8:00 AM - 6:00 PM)
            - G2 : Business with high loads in the evening
            - G3 : Business (24 hours)
            - G4 : Shops / Barbers
            - G5 : Bakery
            - G6 : Weekend operation
        total_nb_occupants : int, optional (used in method 2)
            Number of people living in the household.
        randomizeAppliances : Boolean (only required in method 2)
            - True : Distribute installed appliances randomly
            - False : Use the standard distribution
        lightConfiguration : Integer (only optional in method 2)
            There are 100 light bulb configurations predefined for the
            Stochastic model. Select one by entering an integer in [0, ..., 99]
        occupancy : Array-like (optional, but recommended in method 2)
            Occupancy given at 10-minute intervals for a full year
        do_normalization : bool, optional
            Defines, if stochastic profile (method=2) should be
            normalized to given annualDemand value (default: False).
            If set to False, annual el. demand depends on stochastic el. load
            profile generation. If set to True, does normalization with
            annualDemand
        method_3_type : str, optional
            Defines type of profile for method=3 (default: None)
            Options:
            - 'food_pro': Food production
            - 'metal': Metal company
            - 'rest': Restaurant (with large cooling load)
            - 'sports': Sports hall
            - 'repair': Repair / metal shop
        method_4_type : str, optional
            Defines type of profile for method=4 (default: None)
            - 'metal_1' : Metal company with smooth profile
            - 'metal_2' : Metal company with fluctuation in profile
            - 'warehouse' : Warehouse
        prev_heat_dev : bool, optional
            Defines, if heating devices should be prevented within chosen
            appliances (default: False). If set to True, DESWH, E-INST,
            Electric shower, Storage heaters and Other electric space heating
            are set to zero. Only relevant for method == 2
        app_filename : str, optional
            Path to Appliances file
            (default: None). If set to None, uses default file Appliances.csv
            in \inputs\stochastic_electrical_load\.
            Only relevant, if method == 2.
        light_filename : str, optional
            Path to Lighting configuration file
            (default: None). If set to None, uses default file Appliances.csv
            in \inputs\stochastic_electrical_load\.
            Only relevant, if method == 2.
        season_light_mod : bool, optional
            Defines, if cosine-wave should be used to strengthen seasonal
            influence on lighting (default: False). If True, enlarges
            lighting power demand in winter month and reduces lighting power
            demand in summer month
        light_mod_fac : float, optional
            Define factor, related to maximal lighting power, which is used
            to implement seasonal influence (default: 0.25). Only relevant,
            if season_light_mod == True

        Info
        ----
        The standard load profile can be downloaded here:
        http://www.ewe-netz.de/strom/1988.php

        Average German electricity consumption per household can be found here:
        http://www.die-stromsparinitiative.de/fileadmin/bilder/Stromspiegel/
        Brosch%C3%BCre/Stromspiegel2014web_final.pdf
        """
        src_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

        if method == 0:
            super(ElectricalDemand, self).__init__(environment, loadcurve)

        #  Use standardized load profiles (SLP)
        elif method == 1:
            if not ElectricalDemand.loaded_slp:
                filename = os.path.join(src_path, 'inputs',
                                        'standard_load_profile',
                                        'slp_electrical.xlsx')
                ElectricalDemand.slp = slp_el.load(
                    filename,
                    time_discretization=environment.timer.timeDiscretization)
                ElectricalDemand.loaded_slp = True

            loadcurve = slp_el.get_demand(annualDemand,
                                          ElectricalDemand.slp[profileType],
                                          environment.timer.timeDiscretization)

            super(ElectricalDemand, self).__init__(environment, loadcurve)

        #  Usage of stochastic, el. profile generator for residential buildings
        elif method == 2:

            #  Extract radiation values of weather
            q_direct = environment.weather.qDirect
            q_diffuse = environment.weather.qDiffuse

            #  Extract initial_day
            initial_day = environment.timer.initialDay

            #  Get timestep
            timestep = environment.timer.timeDiscretization

            #  Generate Richadsonpy el. load object instance
            electr_lodad = \
                eload.ElectricLoad(occ_profile=occupancy,
                                   total_nb_occ=total_nb_occupants,
                                   q_direct=q_direct,
                                   q_diffuse=q_diffuse,
                                   annual_demand=annualDemand,
                                   is_sfh=singleFamilyHouse,
                                   path_app=None,
                                   path_light=None,
                                   randomize_appliances=randomizeAppliances,
                                   prev_heat_dev=prev_heat_dev,
                                   light_config=lightConfiguration,
                                   timestep=timestep,
                                   initial_day=initial_day,
                                   season_light_mod=season_light_mod,
                                   light_mod_fac=light_mod_fac,
                                   do_normalization=do_normalization,
                                   calc_profile=True,
                                   save_app_light=False)

            # if app_filename is None:   # Use default
            #     pathApps = os.path.join(src_path, 'inputs',
            #                             'stochastic_electrical_load',
            #                             'Appliances.csv')
            # else:  # Use user defined path
            #     pathApps = app_filename
            #
            # if light_filename is None:  # Use default
            #     pathLights = os.path.join(src_path, 'inputs',
            #                               'stochastic_electrical_load',
            #                               'LightBulbs.csv')
            # else:  # Use user defined path
            #     pathLights = light_filename
            #
            # # Initialize appliances and lights
            # if annualDemand == 0:
            #     if singleFamilyHouse:
            #         annualDemand = self.standard_consumption["SFH"][
            #             total_nb_occupants]
            #     else:
            #         annualDemand = self.standard_consumption["MFH"][
            #             total_nb_occupants]
            #
            # # According to http://www.die-stromsparinitiative.de/fileadmin/
            # # bilder/Stromspiegel/Brosch%C3%BCre/Stromspiegel2014web_final.pdf
            # # roughly 9% of the electricity consumption are due to lighting.
            # # This has to be excluded from the appliances' demand:
            # appliancesDemand = 0.91 * annualDemand
            #
            # #  Get appliances
            # self.appliances = app_model.Appliances(pathApps,
            #                                        annual_consumption=appliancesDemand,
            #                                        randomize_appliances=randomizeAppliances,
            #                                        prev_heat_dev=prev_heat_dev)
            #
            # #  Get lighting configuration
            # self.lights = light_model.load_lighting_profile(pathLights,
            #                                                 lightConfiguration)
            #
            # # Create wrapper object
            # timeDis = environment.timer.timeDiscretization
            # timestepsDay = int(86400 / timeDis)
            # day = environment.timer.currentWeekday
            # self.wrapper = wrapper.Electricity_profile(self.appliances,
            #                                            self.lights)
            #
            # # Make full year simulation
            # demand = []
            # light_load = []
            # app_load = []
            #
            # beam = environment.weather.qDirect
            # diffuse = environment.weather.qDiffuse
            # irradiance = beam + diffuse
            # required_timestamp = np.arange(1440)
            # given_timestamp = timeDis * np.arange(timestepsDay)
            #
            # # Loop over all days
            # for i in range(int(len(irradiance) * timeDis / 86400)):
            #     if (i + day) % 7 in (0, 6):
            #         weekend = True
            #     else:
            #         weekend = False
            #
            #     irrad_day = irradiance[
            #                 timestepsDay * i: timestepsDay * (i + 1)]
            #     current_irradiation = np.interp(required_timestamp,
            #                                     given_timestamp, irrad_day)
            #
            #     current_occupancy = occupancy[144 * i: 144 * (i + 1)]
            #
            #     (el_p_curve, light_p_curve, app_p_curve) = \
            #         self.wrapper.demands(current_irradiation,
            #                              weekend,
            #                              i,
            #                              current_occupancy)
            #
            #     demand.append(el_p_curve)
            #     light_load.append(light_p_curve)
            #     app_load.append(app_p_curve)
            #
            # res = np.array(demand)
            # light_load = np.array(light_load)
            # app_load = np.array(app_load)
            #
            # res = np.reshape(res, res.size)
            # light_load = np.reshape(light_load, light_load.size)
            # app_load = np.reshape(app_load, app_load.size)
            #
            # if season_light_mod:
            #     #  Put cosine-wave on lighting over the year to estimate
            #     #  seasonal influence
            #
            #     light_energy = sum(light_load) * 60
            #
            #     time_array = np.arange(start=0, stop=len(app_load))
            #     time_pi_array = time_array * 2 * np.pi / len(app_load)
            #
            #     cos_array = 0.5 * np.cos(time_pi_array) + 0.5
            #
            #     ref_light_power = max(light_load)
            #
            #     light_load_new = np.zeros(len(light_load))
            #
            #     for i in range(len(light_load)):
            #         if light_load[i] == 0:
            #             light_load_new[i] = 0
            #         elif light_load[i] > 0:
            #             light_load_new[i] = light_load[i] + \
            #                                 light_mod_fac * ref_light_power \
            #                                 * cos_array[i]
            #
            #     light_energy_new = sum(light_load_new) * 60
            #
            #     #  Rescale to original lighting energy demand
            #     light_load_new *= light_energy / light_energy_new
            #
            #     res = light_load_new + app_load
            #
            # #  Change time resolution
            # loadcurve = cr.changeResolution(res, 60, timeDis)
            # # light_load = cr.changeResolution(light_load, 60, timeDis)
            # # app_load = cr.changeResolution(app_load, 60, timeDis)
            #
            # #  Normalize el. load profile to annualDemand
            # if do_normalization:
            #     #  Convert power to energy values
            #     energy_curve = loadcurve * timeDis  # in Ws
            #
            #     #  Sum up energy values (plus conversion from Ws to kWh)
            #     curr_el_dem = sum(energy_curve) / (3600 * 1000)
            #
            #     con_factor = annualDemand / curr_el_dem
            #
            #     #  Rescale load curve
            #     loadcurve *= con_factor

            super(ElectricalDemand, self).__init__(environment,
                                                   electr_lodad.loadcurve)

        #  Generate el. load based on measured, weekly profile
        elif method == 3:

            assert type is not None, 'You need to define a valid type for method 3!'
            assert annualDemand > 0, 'annualDemand has to be larger than 0!'

            if not ElectricalDemand.loaded_weekly_data:
                fpath = os.path.join(src_path, 'inputs', 'measured_el_loads',
                                     'Non_res_weekly_el_profiles.txt')
                ElectricalDemand.weekly_data = \
                    eloader.load_non_res_load_data_weekly(fpath)
                ElectricalDemand.loaded_weekly_data = True

            loadcurve = eloader.gen_annual_el_load(
                ElectricalDemand.weekly_data,
                type=method_3_type,
                start_wd=environment.timer.currentWeekday,
                annual_demand=annualDemand)

            loadcurve = cr.changeResolution(
                loadcurve,
                oldResolution=900,
                newResolution=environment.timer.timeDiscretization)

            super(ElectricalDemand, self).__init__(environment, loadcurve)

        #  Generate el. load based on measured, annual profiles
        elif method == 4:

            assert type is not None, 'You need to define a valid type for method 4!'
            assert annualDemand > 0, 'annualDemand has to be larger than 0!'

            if not ElectricalDemand.load_ann_data:
                fpath = os.path.join(src_path, 'inputs', 'measured_el_loads',
                                     'non_res_annual_el_profiles.txt')
                ElectricalDemand.ann_data = \
                    eloader.load_non_res_load_data_annual(fpath)
                ElectricalDemand.load_ann_data = True

            loadcurve = eloader.get_annual_el_load(ElectricalDemand.ann_data,
                                                   type=method_4_type,
                                                   annual_demand=annualDemand)

            loadcurve = cr.changeResolution(
                loadcurve,
                oldResolution=900,
                newResolution=environment.timer.timeDiscretization)

            super(ElectricalDemand, self).__init__(environment, loadcurve)

        self._kind = "electricaldemand"
        self.method = method
Exemple #7
0
    def __init__(self,
                 environment,
                 method=0,
                 loadcurve=[],
                 annualDemand=0,
                 profileType="H0",
                 singleFamilyHouse=True,
                 total_nb_occupants=0,
                 randomizeAppliances=True,
                 lightConfiguration=0,
                 occupancy=[],
                 do_normalization=False,
                 method_3_type=None,
                 method_4_type=None):
        """
        Parameters
        ----------
        environment : Environment object
            Common to all other objects. Includes time and weather instances
        method : Integer, optional
            - `0` : Provide load curve directly (for all timesteps!)
            - `1` : Standard load profile
            - `2` : Stochastic electrical load model (only residential)
            - `3` : Annual profile based on measured weekly profiles
                    (non-residential)
            - `4` : Annual profile based on measured annual profiles
                    (non-residential)
        loadcurve : Array-like, optional
            Load curve for all investigated time steps
        annualDemand : Float (required for SLP and recommended for method 2)
            Annual electrical demand in kWh.
            If method 2 is chosen but no value is given, a standard value for
            Germany (http://www.die-stromsparinitiative.de/fileadmin/bilder/
            Stromspiegel/Brosch%C3%BCre/Stromspiegel2014web_final.pdf) is used.
        profileType : String (required for SLP; method=1)
            - H0 : Household
            - L0 : Farms
            - L1 : Farms with breeding / cattle
            - L2 : Farms without cattle
            - G0 : Business (general)
            - G1 : Business (workingdays 8:00 AM - 6:00 PM)
            - G2 : Business with high loads in the evening
            - G3 : Business (24 hours)
            - G4 : Shops / Barbers
            - G5 : Bakery
            - G6 : Weekend operation
        total_nb_occupants : int, optional (used in method 2)
            Number of people living in the household.
        randomizeAppliances : Boolean (only required in method 2)
            - True : Distribute installed appliances randomly
            - False : Use the standard distribution
        lightConfiguration : Integer (only optional in method 2)
            There are 100 light bulb configurations predefined for the 
            Stochastic model. Select one by entering an integer in [0, ..., 99]
        occupancy : Array-like (optional, but recommended in method 2)
            Occupancy given at 10-minute intervals for a full year
        do_normalization : bool, optional
            Defines, if stochastic profile (method=2) should be
            normalized to given annualDemand value (default: False).
            If set to False, annual el. demand depends on stochastic el. load
            profile generation. If set to True, does normalization with
            annualDemand
        method_3_type : str, optional
            Defines type of profile for method=3 (default: None)
            Options:
            - 'food_pro': Food production
            - 'metal': Metal company
            - 'rest': Restaurant (with large cooling load)
            - 'sports': Sports hall
            - 'repair': Repair / metal shop
        method_4_type : str, optional
            Defines type of profile for method=4 (default: None)
            - 'metal_1' : Metal company with smooth profile
            - 'metal_2' : Metal company with fluctuation in profile
            - 'warehouse' : Warehouse

        Info
        ----
        The standard load profile can be downloaded here:
        http://www.ewe-netz.de/strom/1988.php
        
        Average German electricity consumption per household can be found here:
        http://www.die-stromsparinitiative.de/fileadmin/bilder/Stromspiegel/
        Brosch%C3%BCre/Stromspiegel2014web_final.pdf
        """
        src_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

        if method == 0:
            super(ElectricalDemand, self).__init__(environment, loadcurve)

        #  Use standardized load profiles (SLP)
        elif method == 1:
            if not ElectricalDemand.loaded_slp:
                filename = os.path.join(src_path, 'inputs',
                                        'standard_load_profile',
                                        'slp_electrical.xlsx')
                ElectricalDemand.slp = slp_el.load(
                    filename,
                    time_discretization=environment.timer.timeDiscretization)
                ElectricalDemand.loaded_slp = True

            loadcurve = slp_el.get_demand(annualDemand,
                                          ElectricalDemand.slp[profileType],
                                          environment.timer.timeDiscretization)

            super(ElectricalDemand, self).__init__(environment, loadcurve)

        #  Usage of stochastic, el. profile generator for residential buildings
        elif method == 2:
            # Initialize appliances and lights
            if annualDemand == 0:
                if singleFamilyHouse:
                    annualDemand = self.standard_consumption["SFH"][
                        total_nb_occupants]
                else:
                    annualDemand = self.standard_consumption["MFH"][
                        total_nb_occupants]

            # According to http://www.die-stromsparinitiative.de/fileadmin/
            # bilder/Stromspiegel/Brosch%C3%BCre/Stromspiegel2014web_final.pdf
            # roughly 9% of the electricity consumption are due to lighting.
            # This has to be excluded from the appliances' demand:
            appliancesDemand = 0.91 * annualDemand

            pathApps = os.path.join(src_path, 'inputs',
                                    'stochastic_electrical_load',
                                    'Appliances.csv')
            self.appliances = app_model.Appliances(
                pathApps,
                annual_consumption=appliancesDemand,
                randomize_appliances=randomizeAppliances)
            pathLights = os.path.join(src_path, 'inputs',
                                      'stochastic_electrical_load',
                                      'LightBulbs.csv')
            self.lights = light_model.load_lighting_profile(
                pathLights, lightConfiguration)

            # Create wrapper object
            timeDis = environment.timer.timeDiscretization
            timestepsDay = int(86400 / timeDis)
            day = environment.timer.currentWeekday
            self.wrapper = wrapper.Electricity_profile(self.appliances,
                                                       self.lights)

            # Make full year simulation
            demand = []
            beam = environment.weather.qDirect
            diffuse = environment.weather.qDiffuse
            irradiance = beam + diffuse
            required_timestamp = np.arange(1440)
            given_timestamp = timeDis * np.arange(timestepsDay)

            # Loop over all days
            for i in range(int(len(irradiance) * timeDis / 86400)):
                if (i + day) % 7 in (0, 6):
                    weekend = True
                else:
                    weekend = False

                irrad_day = irradiance[timestepsDay * i:timestepsDay * (i + 1)]
                current_irradiation = np.interp(required_timestamp,
                                                given_timestamp, irrad_day)

                current_occupancy = occupancy[144 * i:144 * (i + 1)]

                demand.append(
                    self.wrapper.demands(current_irradiation, weekend, i,
                                         current_occupancy)[0])

            res = np.array(demand)
            res = np.reshape(res, res.size)

            loadcurve = cr.changeResolution(res, 60, timeDis)

            #  Normalize el. load profile to annualDemand
            if do_normalization:
                #  Convert power to energy values
                energy_curve = loadcurve * timeDis  # in Ws

                #  Sum up energy values (plus conversion from Ws to kWh)
                curr_el_dem = sum(energy_curve) / (3600 * 1000)

                con_factor = annualDemand / curr_el_dem

                #  Rescale load curve
                loadcurve *= con_factor

            super(ElectricalDemand, self).__init__(environment, loadcurve)

        #  Generate el. load based on measured, weekly profile
        elif method == 3:

            assert type is not None, 'You need to define a valid type for method 3!'
            assert annualDemand > 0, 'annualDemand has to be larger than 0!'

            if not ElectricalDemand.loaded_weekly_data:
                fpath = os.path.join(src_path, 'inputs', 'measured_el_loads',
                                     'Non_res_weekly_el_profiles.txt')
                ElectricalDemand.weekly_data = \
                    eloader.load_non_res_load_data_weekly(fpath)
                ElectricalDemand.loaded_weekly_data = True

            loadcurve = eloader.gen_annual_el_load(
                ElectricalDemand.weekly_data,
                type=method_3_type,
                start_wd=environment.timer.currentWeekday,
                annual_demand=annualDemand)

            loadcurve = cr.changeResolution(
                loadcurve,
                oldResolution=900,
                newResolution=environment.timer.timeDiscretization)

            super(ElectricalDemand, self).__init__(environment, loadcurve)

        #  Generate el. load based on measured, annual profiles
        elif method == 4:

            assert type is not None, 'You need to define a valid type for method 4!'
            assert annualDemand > 0, 'annualDemand has to be larger than 0!'

            if not ElectricalDemand.load_ann_data:
                fpath = os.path.join(src_path, 'inputs', 'measured_el_loads',
                                     'non_res_annual_el_profiles.txt')
                ElectricalDemand.ann_data = \
                    eloader.load_non_res_load_data_annual(fpath)
                ElectricalDemand.load_ann_data = True

            loadcurve = eloader.get_annual_el_load(ElectricalDemand.ann_data,
                                                   type=method_4_type,
                                                   annual_demand=annualDemand)

            loadcurve = cr.changeResolution(
                loadcurve,
                oldResolution=900,
                newResolution=environment.timer.timeDiscretization)

            super(ElectricalDemand, self).__init__(environment, loadcurve)

        self._kind = "electricaldemand"
        self.method = method
Exemple #8
0
    def __init__(self, environment, method=0,
                 loadcurve=[], 
                 livingArea=0, specificDemand=0, profile_type='HEF',
                 zoneParameters=None, T_m_init=None, ventilation=0,
                 TCoolingSet=200, THeatingSet=-50, occupancy=0,
                 appliances=0, lighting=0):
        """
        Parameters
        ----------
        environment : Environment object
            Common to all other objects. Includes time and weather instances
        method : integer, optional
            - `0` : Provide load curve directly
            - `1` : Use thermal standard load profile
            - `2` : Use ISO 13790 standard to compute thermal load
            - `3` : Use example thermal load profiles, generated with
                    Modelica AixLib low order model (only valid for residential
                    building and test reference year weather file for 2010,
                    region 5!)
        loadcurve : Array-like, optional
            Load curve for all investigated time steps
            Requires ``method=0``.
        livingArea : Float, optional
            Living area of the apartment in m2
            Requires ``method=1``
        specificDemand : Float, optional
            Specific thermal demand of the building in kWh/(m2 a)
            Requires ``method=1``
        profile_type : str, optional
            Thermal SLP profile name
            Requires ``method=1``
            - `HEF` : Single family household
            - `HMF` : Multi family household
            - `GBA` : Bakeries
            - `GBD` : Other services
            - `GBH` : Accomodations
            - `GGA` : Restaurants
            - `GGB` : Gardening
            - `GHA` : Retailers
            - `GHD` : Summed load profile business, trade and services
            - `GKO` : Banks, insurances, public institutions
            - `GMF` : Household similar businesses
            - `GMK` : Automotive
            - `GPD` : Paper and printing
            - `GWA` : Laundries
        zoneParameters : ZoneParameters object, optional
            Parameters of the building (floor area, building class, etc.). 
            Requires ``method=2``.
        T_m_init : Float, optional
            Initial temperature of the internal heat capacity.
            Requires ``method=2``.
        ventilation : Array-like, optional
            Ventilation rate in 1/h.
            Requires ``method=2``.
        TCoolingSet : Array-like, optional
            Cooling starts if the room temperature exceeds this value.
            Requires ``method=2``.
        THeatingSet : Array-like, optional
            Heating starts if the room temperature drops below this value.
            Requires ``method=2``.
        occupancy : Array-like, optional
            Full year occupancy profile.
            Requires ``method=2``.
        appliances : Array-like, optional
            Internal gains from electrical appliances in Watt.
            Requires ``method=2``.
        lighting : Array-like, optional
            Internal gains from lighting in Watt.
            Requires ``method=2``.
        
        Info
        ----
        The thermal standard load profile is based on the disseratation of
        Mark Hellwig. 
        "Entwicklung und Anwendung parametrisierter Standard-Lastprofile",
        TU München, Germany, 2003.
        
        URL : http://mediatum.ub.tum.de/doc/601557/601557.pdf
        """
        self.method = method
        
        if method == 0:
            #  Hand over own power curve
            super(SpaceHeating, self).__init__(environment, loadcurve)

        elif method == 1:
            #  Generate standardized thermal load profile (SLP)
            timeDis = environment.timer.timeDiscretization
            if not SpaceHeating.loaded_slp:
                src_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
                folder = os.path.join(src_path, 'inputs', 'standard_load_profile')
                f_hour = os.path.join(folder, 'slp_thermal_hourly_factors.xlsx')
                f_prof = os.path.join(folder, 'slp_thermal_profile_factors.xlsx')
                f_week = os.path.join(folder, 'slp_thermal_week_day_factors.xlsx')
                SpaceHeating.slp_hour = slp_th.load_hourly_factors(f_hour,
                                                                   timeDis)
                SpaceHeating.slp_prof = slp_th.load_profile_factors(f_prof)
                SpaceHeating.slp_week = slp_th.load_week_day_factors(f_week)
                                
                SpaceHeating.loaded_slp = True
            
            annual_demand = livingArea * specificDemand  # kWh
            profile = 1
    
            fun = slp_th.calculate
            loadcurve = fun(environment.weather.tAmbient,
                            environment.timer.currentDay,
                            SpaceHeating.slp_prof[profile_type][profile],
                            SpaceHeating.slp_week[profile_type],
                            SpaceHeating.slp_hour[profile_type],
                            annual_demand)
            
            super(SpaceHeating, self).__init__(environment, loadcurve)
            
        elif method == 2:
            #  Generate thermal load with ISO model
            self.zoneParameters = zoneParameters
            # Create zoneInputs (this already creates the full year inputs!)
            self.zoneInputs = zi.ZoneInputs(environment,
                                            zoneParameters,
                                            T_m_init,
                                            ventilation=ventilation,
                                            occupancy=occupancy,
                                            appliances=appliances,
                                            lighting=lighting)
            
            calc = pycity_base.functions.zoneModel.calc
            res = calc(zoneParameters=self.zoneParameters,
                           zoneInputs=self.zoneInputs, 
                           TCoolingSet=TCoolingSet,
                           THeatingSet=THeatingSet,
                           limitHeating=np.inf, 
                           limitCooling=-np.inf, 
                           beQuiet=True)
            
            self.loadcurve = res[0]
            self.T_op = res[1]
            self.T_m = res[2]
            self.T_i = res[3]
            self.T_s = res[4]

        elif method == 3:
            #  Use Modelica thermal load profile for residential building

            if not SpaceHeating.loaded_sim_profile:
                src_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
                folder = os.path.join(src_path, 'inputs', 'simulated_profiles',
                                      'res_building')
                dpath = os.path.join(folder, 'res_b_modelica_th_load_try_2010_5.txt')

                SpaceHeating.sim_prof_data = np.genfromtxt(dpath,
                                                           delimiter='\t',
                                                           skip_header=2)

                SpaceHeating.loaded_sim_profile = True

            annual_demand = livingArea * specificDemand  # kWh

            #  Extract first profile
            loadcurve = copy.deepcopy(SpaceHeating.sim_prof_data[:, 1])

            #  Rescale profile to annual_demand
            con_factor = (1000 * annual_demand) / sum(loadcurve)
            loadcurve *= con_factor

            #  Change resolution
            loadcurve = chres.changeResolution(loadcurve, oldResolution=3600,
                                               newResolution=environment.timer.timeDiscretization)

            super(SpaceHeating, self).__init__(environment, loadcurve)
            
        self._kind = "spaceheating"
if __name__ == '__main__':
    this_path = os.path.dirname(os.path.abspath(__file__))

    search_path = os.path.join(this_path, 'profiles')

    #  Generate ProfilePool object
    prof_pool = ProfilePool(path_to_npz_folder=search_path)

    #  Get occ, el. and dhw profile
    (occ_profile, el_profile, dhw_profile) = \
        prof_pool.get_occ_el_dhw_profile(nb_occupants=3)

    #  Change resolution of occupancy profile from 600 to 60 seconds
    occ_profile = chres.changeResolution(occ_profile,
                                         oldResolution=600,
                                         newResolution=60)

    el_energy = sum(el_profile) * 60 / (3600 * 1000)
    print('El. energy in kWh: ', el_energy)

    dhw_energy = sum(dhw_profile) * 60 / (3600 * 1000)
    print('Hot water net energy in kWh: ', dhw_energy)

    time_array = np.arange(0, 365 * 24 * 3600, 60)
    time_array = time_array / 3600

    fig = plt.figure()
    plt.subplot(311)
    plt.plot(time_array, occ_profile)
    plt.ylabel('Occupancy')
def full_year_computation(occupancy,
                          profiles,
                          time_dis=3600,
                          initial_day=0,
                          temperature_difference=35):
    """
    Parameters
    ----------
    occupancy : array_like
        Full year, 10-minute-wise sampled occupancy profile. All values have
        to be integers.
    profiles : dictionary
        All probability distributions. The dictionary has to have the 
        following structure: 
            - Top level: [`wd_mw`, `we_mw`, `wd`, `we`] (strings)
            - Within `we` and `wd`: [`1`, `2`, `3`, `4`, `5`, `6`] (integers)
    time_dis : integer
        Time discretization in seconds.
    initial_day : integer
        - 0 : Monday
        - 1 : Tuesday
        - 2 : Wednesday
        - 3 : Thursday
        - 4 : Friday
        - 5 : Saturday
        - 6 : Sunday
    temperature_difference : float
        How much does the tap water has to be heated up? Either enter a float
        or an array with the same dimension as probability_profiles.
    
    Returns
    -------
    water : array_like
        Tap water volume flow in liters per hour.
    heat : array_like
        Resulting minute-wise sampled heat demand in Watt.
        The heat capacity of water is assumed to be 4180 J/(kg.K) and the
        density is assumed to be 980 kg/m3
    """
    # Initialization
    number_days = int(len(occupancy) / 144)

    water = np.zeros(len(occupancy) * 10)
    heat = np.zeros(len(occupancy) * 10)

    for day in range(number_days):
        # Is the current day on a weekend?
        if (day + initial_day) % 7 >= 5:
            probability_profiles = profiles["we"]
            average_profile = profiles["we_mw"]
        else:
            probability_profiles = profiles["wd"]
            average_profile = profiles["wd_mw"]

        # Get water and heat demand for the current day
        res = compute_daily_demand(probability_profiles, average_profile,
                                   occupancy[day * 144:(day + 1) * 144], day,
                                   temperature_difference)
        (current_water, current_heat) = res

        # Include current_water and current_heat in water and heat
        water[day * 1440:(day + 1) * 1440] = current_water
        heat[day * 1440:(day + 1) * 1440] = current_heat

    # Change sampling time to the given input
    water = cr.changeResolution(water, 60, time_dis, "sum") / time_dis * 60
    heat = cr.changeResolution(heat, 60, time_dis, "sum") / time_dis * 60

    # Return results
    return (water, heat)
    # Max. occupancy is 5 people simultaneously
    occupancy = np.random.geometric(p=0.8, size=6 * 24 * 365) - 1
    occupancy = np.minimum(5, occupancy)

    # Set initial_day
    initial_day = 0

    # Run simulation
    (water, heat) = full_year_computation(occupancy,
                                          profiles,
                                          time_dis=60,
                                          initial_day=initial_day)

    # Change time resolution to 15 minutes
    dt = 15
    hd = cr.changeResolution(heat, 60, dt * 60, "sum") / dt

    # Plot heat demand
    import matplotlib.pyplot as plt
    ax1 = plt.subplot(2, 1, 1)
    plt.plot(np.arange(len(heat)) / 60, heat, color="b", linewidth=2)
    plt.step((np.arange(len(hd)) * dt + dt) / 60, hd, color="r", linewidth=2)
    plt.ylabel("Heat demand in Watt")
    plt.xlim((0, 8760))

    plt.subplot(2, 1, 2, sharex=ax1)
    plt.step((np.arange(len(occupancy)) * 10 + 10) / 60,
             occupancy,
             linewidth=2)
    plt.ylabel("Active occupants")
    offset = 0.2