diff --git a/cluster_demands.xlsx b/cluster_demands.xlsx new file mode 100644 index 00000000..b8634333 Binary files /dev/null and b/cluster_demands.xlsx differ diff --git a/clusters.py b/clusters.py new file mode 100644 index 00000000..70278c10 --- /dev/null +++ b/clusters.py @@ -0,0 +1,124 @@ + +import numpy as np +import pandas as pd +from sklearn.preprocessing import StandardScaler +from sklearn.decomposition import PCA +from sklearn.cluster import KMeans +import matplotlib.pyplot as plt + + +def extract_building_data(scenario, demand_types): + """ + Extracts energy demand data for each building from the scenario dictionary. + + Args: + scenario (dict): Scenario dictionary containing building data. + demand_types (list): List of demand types to extract. + + Returns: + pd.DataFrame: DataFrame with buildings as rows and demand types as columns. + """ + data = [] + building_ids = [] + + for building_id, demand_data in scenario.items(): + building_row = [] + for demand_type in demand_types: + building_row.extend(demand_data[demand_type]) + data.append(building_row) + building_ids.append(building_id) + + return pd.DataFrame(data, index=building_ids, + columns=[f"{demand_type}_{i}" for demand_type in demand_types for i in range(8760)]) + +# Plot the data +print('test') +def cluster_buildings(scenario, demand_types, n_clusters=4,n_components=2): + """ + Clusters buildings based on their energy demand. + + Args: + scenario (dict): Scenario dictionary containing building data. + demand_types (list): List of demand types to use for clustering. + n_clusters (int): Number of clusters to form. + + Returns: + pd.DataFrame: DataFrame with building IDs and their corresponding cluster labels. + """ + # Extract building data + building_data = extract_building_data(scenario, demand_types) + + # Standardize the data + scaler = StandardScaler() + building_data_scaled = scaler.fit_transform(building_data) + + # Optional: Dimensionality reduction with PCA + pca = PCA(n_components) + building_data_pca = pca.fit_transform(building_data_scaled) + + # Clustering with K-Means + kmeans = KMeans(n_clusters=n_clusters, random_state=42) + kmeans.fit(building_data_pca) + + # Assign cluster labels to buildings + clusters = kmeans.labels_ + + # Create a DataFrame with building IDs and cluster labels + clustered_buildings = pd.DataFrame({ + 'building_id': building_data.index, + 'cluster': clusters + }) + + return clustered_buildings + + +# Example usage +scenario_data = scenario['efficient with PV+4Pipe+DHW'] # Use 'baseline' or 'efficient with PV' +demand_types = [ + 'heating_consumption_kWh' +] + +# Cluster buildings +clustered_buildings = cluster_buildings(scenario_data, demand_types, n_clusters=4,n_components=20) + +# Visualize clusters +plt.figure(figsize=(10, 6)) +plt.scatter(clustered_buildings['building_id'], clustered_buildings['cluster'], c=clustered_buildings['cluster'], + cmap='viridis') +plt.xlabel('Building ID') +plt.ylabel('Cluster') +plt.title('Building Clusters Based on Energy Demand') +plt.colorbar(label='Cluster') +# Save the plot +plt.savefig(os.path.join(output_path, 'clusters.png')) +plt.close() + +# Plot the data +print('test') + + + +output_path_clusters = output_path / 'clustered_buildings_4.xlsx' +clustered_buildings.to_excel(output_path_clusters, index=False) + +#clusters made in QGIS +clusters_path=output_path/ "clusters" / 'updated_buildings_with_clusters.geojson' + +with open(clusters_path, 'r') as f: + clusters = json.load(f) + +def extract_cluster(key, clusters): + + for idx, feature in enumerate(clusters['features']): + if str(feature['properties']['id']) == str(key): + cluster=feature['properties']['Cluster_ID'] + + return cluster +cluster_dic={} +scenario_data = scenario['efficient with PV+4Pipe+DHW'] +for key, data in scenario_data.items(): + cluster_dic[key]=extract_cluster(key, clusters) + +# +# cluster_df = pd.DataFrame.from_dict(cluster_dic, orient='index') +# cluster_df.to_csv(output_path/'clusters.csv') diff --git a/comparing.py b/comparing.py index cfe69875..25aa7e34 100644 --- a/comparing.py +++ b/comparing.py @@ -52,14 +52,6 @@ percentage_data = { 1690: {"type1_%": 0.94, "type2_%": 0.06, "type3_%": 0, "roof_area": 2189.732519, "total_floor_area": 28466.52275}, 1691: {"type1_%": 0.75, "type2_%": 0.25, "type3_%": 0, "roof_area": 3159.077523, "total_floor_area": 31590.77523}, } -# Define the demand types to be plotted -demand_types = [ - 'heating_demand_kWh', - 'cooling_demand_kWh', - 'domestic_hot_water_heat_demand_kWh', - 'appliances_electrical_demand_kWh', - 'lighting_electrical_demand_kWh' -] # # Function to extract demand data from the GeoJSON # def extract_demand_data(geojson_data, demand_type, period_start, period_end): @@ -122,6 +114,14 @@ demand_types = [ # plot_comparison(selected_buildings, baseline_summer, efficient_summer, range(period_start_summer, period_end_summer), f'One Week in Summer - Comparison - {demand_type}') # +# Define the demand types to be plotted +demand_types = [ + 'heating_demand_kWh', + 'cooling_demand_kWh', + 'domestic_hot_water_heat_demand_kWh', + 'appliances_electrical_demand_kWh', + 'lighting_electrical_demand_kWh' +] # Function to extract and sum demand data from the GeoJSON def extract_and_sum_demand_data(geojson_data, demand_type, period_start, period_end): diff --git a/hub/city_model_structure/building.py b/hub/city_model_structure/building.py index ed7ba168..15a1eff1 100644 --- a/hub/city_model_structure/building.py +++ b/hub/city_model_structure/building.py @@ -810,37 +810,37 @@ class Building(CityObject): Get total electricity produced onsite in J return: dict """ - orientation_losses_factor = {cte.MONTH: {'north': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - 'east': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - 'south': [2.137931, 1.645503, 1.320946, 1.107817, 0.993213, 0.945175, - 0.967949, 1.065534, 1.24183, 1.486486, 1.918033, 2.210526], - 'west': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}, - cte.YEAR: {'north': [0], - 'east': [0], - 'south': [1.212544], - 'west': [0]} - } - - # Add other systems whenever new ones appear - if self.energy_systems is None: - return self._onsite_electrical_production - for energy_system in self.energy_systems: - for generation_system in energy_system.generation_systems: - if generation_system.system_type == cte.PHOTOVOLTAIC: - if generation_system.electricity_efficiency is not None: - _efficiency = float(generation_system.electricity_efficiency) - else: - _efficiency = 0 - self._onsite_electrical_production = {} - for _key in self.roofs[0].global_irradiance.keys(): - _results = [0 for _ in range(0, len(self.roofs[0].global_irradiance[_key]))] - for surface in self.roofs: - if _key in orientation_losses_factor: - _results = [x + y * _efficiency * surface.perimeter_area - * surface.solar_collectors_area_reduction_factor * z - for x, y, z in zip(_results, surface.global_irradiance[_key], - orientation_losses_factor[_key]['south'])] - self._onsite_electrical_production[_key] = _results + # orientation_losses_factor = {cte.MONTH: {'north': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + # 'east': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + # 'south': [2.137931, 1.645503, 1.320946, 1.107817, 0.993213, 0.945175, + # 0.967949, 1.065534, 1.24183, 1.486486, 1.918033, 2.210526], + # 'west': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}, + # cte.YEAR: {'north': [0], + # 'east': [0], + # 'south': [1.212544], + # 'west': [0]} + # } + # + # # Add other systems whenever new ones appear + # if self.energy_systems is None: + # return self._onsite_electrical_production + # for energy_system in self.energy_systems: + # for generation_system in energy_system.generation_systems: + # if generation_system.system_type == cte.PHOTOVOLTAIC: + # if generation_system.electricity_efficiency is not None: + # _efficiency = float(generation_system.electricity_efficiency) + # else: + # _efficiency = 0 + # self._onsite_electrical_production = {} + # for _key in self.roofs[0].global_irradiance.keys(): + # _results = [0 for _ in range(0, len(self.roofs[0].global_irradiance[_key]))] + # for surface in self.roofs: + # if _key in orientation_losses_factor: + # _results = [x + y * _efficiency * surface.perimeter_area + # * surface.solar_collectors_area_reduction_factor * z + # for x, y, z in zip(_results, surface.global_irradiance[_key], + # orientation_losses_factor[_key]['south'])] + # self._onsite_electrical_production[_key] = _results return self._onsite_electrical_production @property diff --git a/hub/data/energy_systems/montreal_future_systems.xml b/hub/data/energy_systems/montreal_future_systems.xml index 64f26baa..1db38ecf 100644 --- a/hub/data/energy_systems/montreal_future_systems.xml +++ b/hub/data/energy_systems/montreal_future_systems.xml @@ -1410,8 +1410,8 @@ cooling - 23 - 16 + 25 + 17 diff --git a/main.py b/main.py index 4a19baee..175263d6 100644 --- a/main.py +++ b/main.py @@ -14,13 +14,14 @@ import subprocess from hub.imports.results_factory import ResultFactory from hub.imports.energy_systems_factory import EnergySystemsFactory from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory +from scripts.solar_angles import CitySolarAngles import hub.helpers.constants as cte from hub.exports.exports_factory import ExportsFactory -from scripts.solar_angles import CitySolarAngles -from scripts.radiation_tilted import RadiationTilted - +from scripts.pv_sizing_and_simulation import PVSizingSimulation +import pandas as pd import geopandas as gpd import json + #%% # ----------------------------------------------- # Specify the GeoJSON file path #%% # ----------------------------------------------- @@ -41,7 +42,7 @@ cost_analysis_output_path.mkdir(parents=True, exist_ok=True) #%% # ----------------------------------------------- geojson_file_path_baseline = output_path / 'updated_buildings_with_all_data_baseline.geojson' -geojson_file_path_2024 = output_path / 'updated_buildings_with_all_data.geojson' +geojson_file_path_2024 = output_path / 'updated_buildings_with_all_data_2024.geojson' with open(geojson_file_path_baseline , 'r') as f: building_type_data = json.load(f) with open(geojson_file_path_2024, 'r') as f: @@ -54,47 +55,14 @@ city = GeometryFactory('geojson', year_of_construction_field='year_built', function_field='building_type', function_to_hub=Dictionaries().montreal_function_to_hub_function).city -#%%----------------------------------------------- +#%%---------------------------------------------- # Enrich city data -#%% # ----------------------------------------------- +#%% # ---------------------------------------------- ConstructionFactory('nrcan', city).enrich() UsageFactory('nrcan', city).enrich() WeatherFactory('epw', city).enrich() # #energy plus is not going to be processed here, as demand has been obtained before # energy_plus_workflow(city) -#%%----------------------------------------------- -# """SRA""" -#%% # ----------------------------------------------- -ExportsFactory('sra', city, sra_output_path).export() -sra_path = (sra_output_path / f'{city.name}_sra.xml').resolve() -subprocess.run(['sra', str(sra_path)]) -ResultFactory('sra', city, sra_output_path).enrich() -solar_angles = CitySolarAngles(city.name, - city.latitude, - city.longitude, - tilt_angle=45, - surface_azimuth_angle=180).calculate -for building in city.buildings: - ghi = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]] - RadiationTilted(building, - solar_angles, - tilt_angle=45, - ghi=ghi).enrich() -# building_names = [] -# for building in city.buildings: -# building_names.append(building.name) -# -# df = pd.DataFrame(columns=building_names) -# df1 = pd.DataFrame(columns=building_names) -# print('test') -# for building in city.buildings: -# # if building.name in selected_buildings_list: -# df[f'{building.name}'] = building.roofs[0].global_irradiance[cte.HOUR] -# df1[f'{building.name}'] = building.roofs[0].global_irradiance_tilted[cte.HOUR] -# -# df.to_csv('solar_radiation_horizontal_selected_buildings.csv') -# df1.to_csv('solar_radiation_tilted_selected_buildings.csv') - #%% # ----------------------------------------------- #"""Enrich city with geojson file data""" #%% # ----------------------------------------------- @@ -169,50 +137,616 @@ print('test') #%% # ----------------------------------------------- for building in city.buildings: - building.energy_systems_archetype_name = 'system 1 electricity pv' - + building.energy_systems_archetype_name = 'system 1 electricity' EnergySystemsFactory('montreal_custom', city).enrich() -# for building in city.buildings: -# energy_systems = building.energy_systems -# for energy_system in energy_systems: -# generation_units = energy_system.generation_systems -# if cte.HEATING in energy_system.demand_types: -# for generation_unit in generation_units: -# generation_unit.heat_efficiency = 0.96 -def to_dict(building, total_floor_area): + +def baseline_to_dict(building): return { - 'roof_area': building.floor_area, - 'total_floor_area': total_floor_area, - 'heating_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.energy_consumption_breakdown[cte.HOUR]], - 'cooling_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.cooling_demand[cte.HOUR]], - 'domestic_hot_water_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.domestic_hot_water_heat_demand[cte.HOUR]], + 'heating_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.heating_consumption[cte.HOUR]], + 'cooling_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.cooling_consumption[cte.HOUR]], + 'domestic_hot_water_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.domestic_hot_water_consumption[cte.HOUR]], 'appliances_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.appliances_electrical_demand[cte.HOUR]], 'lighting_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.lighting_electrical_demand[cte.HOUR]] } buildings_dic={} +for building in city.buildings: + buildings_dic[building.name]=baseline_to_dict(building) +scenario={} + +scenario['baseline']=buildings_dic +print("Scenario 1: Baseline is performed successfully") + + + +del city +del buildings_dic +del building_type_data + +#%%----------------------------------------------- +# Scenario 2 +#%% # ----------------------------------------------- + +# Create city object from GeoJSON file +city = GeometryFactory('geojson', + path=geojson_file_path_2024, + height_field='maximum_roof_height', + year_of_construction_field='year_built', + function_field='building_type', + function_to_hub=Dictionaries().montreal_function_to_hub_function).city +#%%----------------------------------------------- +# Enrich city data +#%% # ----------------------------------------------- +ConstructionFactory('nrcan', city).enrich() +UsageFactory('nrcan', city).enrich() +WeatherFactory('epw', city).enrich() + +enrich_buildings_with_geojson_data (building_type_data_2024, city) + +def to_dict(building,hourly_pv): + return { + 'heating_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.heating_consumption[cte.HOUR]], + 'cooling_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.cooling_consumption[cte.HOUR]], + 'domestic_hot_water_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.domestic_hot_water_consumption[cte.HOUR]], + 'appliances_consumption_kWh':[x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.appliances_electrical_demand[cte.HOUR]], + 'lighting_consumption_kWh': [x / (cte.WATTS_HOUR_TO_JULES * 1000) for x in building.lighting_electrical_demand[cte.HOUR]], + 'hourly_pv_kWh': [x /(cte.WATTS_HOUR_TO_JULES * 1000) for x in hourly_pv] + } +buildings_dic={} for building in city.buildings: + building.energy_systems_archetype_name = 'system 1 electricity pv' - total_floor_area = 0 - for thermal_zone in building.thermal_zones_from_internal_zones: - total_floor_area += thermal_zone.total_floor_area +EnergySystemsFactory('montreal_custom', city).enrich() +# #%%----------------------------------------------- +# # """SRA""" +# #%% # ----------------------------------------------- +ExportsFactory('sra', city, output_path).export() +sra_path = (output_path / f'{city.name}_sra.xml').resolve() +subprocess.run(['sra', str(sra_path)]) +ResultFactory('sra', city, output_path).enrich() +solar_angles = CitySolarAngles(city.name, + city.latitude, + city.longitude, + tilt_angle=45, + surface_azimuth_angle=180).calculate +df = pd.DataFrame() +df.index = ['yearly lighting (kWh)', 'yearly appliance (kWh)', 'yearly heating (kWh)', 'yearly cooling (kWh)', + 'yearly dhw (kWh)', 'roof area (m2)', 'used area for pv (m2)', 'number of panels', 'pv production (kWh)'] +for building in city.buildings: + ghi = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]] + pv_sizing_simulation = PVSizingSimulation(building, + solar_angles, + tilt_angle=45, + module_height=1, + module_width=2, + ghi=ghi) + pv_sizing_simulation.pv_output() + yearly_lighting = building.lighting_electrical_demand[cte.YEAR][0] / 1000 + yearly_appliance = building.appliances_electrical_demand[cte.YEAR][0] / 1000 + yearly_heating = building.heating_demand[cte.YEAR][0] / (3.6e6 * 3) + yearly_cooling = building.cooling_demand[cte.YEAR][0] / (3.6e6 * 4.5) + yearly_dhw = building.domestic_hot_water_heat_demand[cte.YEAR][0] / 1000 + roof_area = building.roofs[0].perimeter_area + used_roof = pv_sizing_simulation.available_space() + number_of_pv_panels = pv_sizing_simulation.total_number_of_panels + yearly_pv = building.onsite_electrical_production[cte.YEAR][0] / (3.6e6) + hourly_pv = building.onsite_electrical_production[cte.HOUR] + df[f'{building.name}'] = [yearly_lighting, yearly_appliance, yearly_heating, yearly_cooling, yearly_dhw, roof_area, + used_roof, number_of_pv_panels, yearly_pv] + buildings_dic[building.name]=to_dict(building,hourly_pv) + +# %%----------------------------------------------- +# """South facing facades""" +# %% # ----------------------------------------------- +# Function to convert radians to degrees +import math +def radians_to_degrees(radians): + return radians * (180 / math.pi) +# Step 1: Create the walls_id dictionary +walls_id={} + +for building in city.buildings: + ids = {} + for walls in building.walls: + id=walls.id + azimuth_degree=radians_to_degrees(float(walls.azimuth)) + if azimuth_degree>90.0 or azimuth_degree 31: + sheet_name = sheet_name[:31] # Truncate to 31 characters if necessary + # Write the DataFrame to a specific sheet named after the building_id + df_demands.to_excel(writer, sheet_name=sheet_name, index=False) + + +print("district balance data is exported successfully") + + +import pandas as pd + +# Assuming your scenario dictionary is already defined as follows: +# scenario = { +# 'baseline': { ... }, +# 'efficient with PV': { ... } +# } + + +def dict_to_df_col_wise(building_data): + """ + Converts a dictionary of building data to a DataFrame. + + Args: + building_data (dict): Dictionary containing building data where keys are building ids and values are dictionaries + with hourly data for various demand types. + + Returns: + pd.DataFrame: DataFrame with columns for each building and demand type. + """ + # Create a dictionary to hold DataFrames for each demand type + df_dict= {} + + # Loop over each building + for building_id, data in building_data.items(): + # Create a DataFrame for this building's data + building_df = pd.DataFrame(data) + + # Rename columns to include building_id + building_df.columns = [f"{building_id}_{col}" for col in building_df.columns] + + # Add this DataFrame to the dictionary + df_dict[building_id] = building_df + + # Concatenate all building DataFrames column-wise + result_df = pd.concat(df_dict.values(), axis=1) + + return result_df + +# Create DataFrames for each scenario +baseline_df = dict_to_df_col_wise(scenario['baseline']) +efficient_with_pv_df = dict_to_df_col_wise(scenario['efficient with PV']) +efficient_with_pv_hps = dict_to_df_col_wise(scenario['efficient with PV+4Pipe+DHW']) + + +# Write the DataFrames to an Excel file with two separate sheets +with pd.ExcelWriter(r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\scenario_data.xlsx') as writer: + baseline_df.to_excel(writer, sheet_name='baseline', index=True) + efficient_with_pv_df.to_excel(writer, sheet_name='efficient with PV', index=True) + efficient_with_pv_hps.to_excel(writer, sheet_name='efficient with HPs_2', index=True) + +print("hourly data has been successfully exported per building to scenario_data.xlsx") + + + +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np + + +def convert_hourly_to_monthly(hourly_data): + """ + Converts hourly data to monthly data by summing up the values for each month. + + Args: + hourly_data (list): List of hourly data (length 8760). + + Returns: + list: List of monthly data (length 12). + """ + hourly_series = pd.Series(hourly_data, index=pd.date_range(start='1/1/2023', periods=8760, freq='H')) + monthly_data = hourly_series.resample('M').sum() + return monthly_data.tolist() + +import os +def plot_stacked_demands_vs_pv(district_demand, demand_types, output_path, pv_type='hourly_pv_kWh'): + """ + Plots the stacked monthly demand for each scenario and compares it to the PV data. + + Args: + district_demand (dict): Dictionary with scenario keys and demand data. + demand_types (list): List of demand types to plot. + output_path (str): Path to save the plots. + pv_type (str): The PV data type to compare against. + """ + os.makedirs(output_path, exist_ok=True) + + for scenario_key, demand_data in district_demand.items(): + # Convert hourly data to monthly data for each demand type + monthly_data = {demand_type: convert_hourly_to_monthly(demand_data[demand_type]) for demand_type in + demand_types} + monthly_pv = convert_hourly_to_monthly(demand_data.get(pv_type, [0] * 8760)) + + # Create a DataFrame for easier plotting + combined_data = pd.DataFrame(monthly_data) + combined_data['Month'] = range(1, 13) + combined_data['PV'] = monthly_pv + + # Plotting + fig, ax1 = plt.subplots(figsize=(14, 8)) + + # Plot stacked demands + combined_data.set_index('Month', inplace=True) + combined_data[demand_types].plot(kind='bar', stacked=True, ax=ax1, colormap='tab20') + + ax1.set_xlabel('Month') + ax1.set_ylabel('Energy Demand (kWh)') + ax1.set_title(f'Monthly Energy Demand and PV Generation for {scenario_key}') + + # Plot PV data on the secondary y-axis + ax2 = ax1.twinx() + ax2.plot(combined_data.index, combined_data['PV'], color='black', linestyle='-', marker='o', + label='PV Generation') + ax2.set_ylabel('PV Generation (kWh)') + + # Add legends + ax1.legend(loc='upper left') + ax2.legend(loc='upper right') + + ax1.set_xticks(combined_data.index) + ax1.set_xticklabels(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']) + + # Save the plot + plt.savefig(os.path.join(output_path, f'{scenario_key}_monthly_demand_vs_pv.png')) + plt.close() + + +# Example usage +# district_demand = extract_and_sum_demand_data(scenario, demand_types) + +# Specify the demand types and PV type +demand_types = [ + 'heating_consumption_kWh', + 'cooling_consumption_kWh', + 'domestic_hot_water_consumption_kWh', + 'appliances_consumption_kWh', + 'lighting_consumption_kWh' +] + +# Plot the data +plot_stacked_demands_vs_pv(district_demand, demand_types, output_path) +# Plot the data +print('test') +import csv \ No newline at end of file diff --git a/processor.py b/processor.py index 094aaac2..685e063a 100644 --- a/processor.py +++ b/processor.py @@ -3,16 +3,18 @@ from pathlib import Path import pandas as pd import geopandas as gpd - +#%%----------------------------------------------- +# """This code takes different results from energy plus with different building uses and obtains a unique geojson that combines all of them""" +#%% # ----------------------------------------------- #define output path output_path = (Path(__file__).parent / 'out_files').resolve() output_path.mkdir(parents=True, exist_ok=True) # Define output folders output_folders = ['building_type', 'building_type_2', 'building_type_3'] #output paths containing energy+ results are read -path1=r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\building_type\updated_buildings.geojson' -path2=r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\building_type_2\updated_buildings.geojson' -path3=r'C:\Users\a_gabald\PycharmProjects\summer_course_2024\out_files\building_type_3\updated_buildings.geojson' +path1=output_path / '1990_and_2019'/'building_type' / 'updated_buildings.geojson' +path2=output_path / '1990_and_2019'/ 'building_type_2' / 'updated_buildings.geojson' +path3=output_path / '1990_and_2019'/'building_type_3' / 'updated_buildings.geojson' with open(path1, 'r') as f: building_type_data = json.load(f) with open(path2, 'r') as f: diff --git a/scripts/energy_system_sizing_and_simulation_factory.py b/scripts/energy_system_sizing_and_simulation_factory.py index 9a0e14bb..ceb01a65 100644 --- a/scripts/energy_system_sizing_and_simulation_factory.py +++ b/scripts/energy_system_sizing_and_simulation_factory.py @@ -4,8 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2022 Concordia CERC group Project Coder Saeed Ranjbar saeed.ranjbar@mail.concordia.ca """ - -from scripts.system_simulation_models.archetype13 import Archetype13 +from scripts.system_simulation_models.archetype13_electric import Archetype13 +# from scripts.system_simulation_models.archetype13 import Archetype13 from scripts.system_simulation_models.archetype13_stratified_tes import Archetype13Stratified from scripts.system_simulation_models.archetype1 import Archetype1 from scripts.system_simulation_models.archetypes14_15 import Archetype14_15 diff --git a/scripts/system_simulation_models/archetype1.py b/scripts/system_simulation_models/archetype1.py index bd17efd4..5c56ec66 100644 --- a/scripts/system_simulation_models/archetype1.py +++ b/scripts/system_simulation_models/archetype1.py @@ -16,7 +16,8 @@ class Archetype1: self._domestic_hot_water_peak_load = building.domestic_hot_water_peak_load[cte.YEAR][0] self._hourly_heating_demand = [0] + [demand / 3600 for demand in building.heating_demand[cte.HOUR]] self._hourly_cooling_demand = [demand / 3600 for demand in building.cooling_demand[cte.HOUR]] - self._hourly_dhw_demand = building.domestic_hot_water_heat_demand[cte.HOUR] + self._hourly_dhw_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in + building.domestic_hot_water_heat_demand[cte.HOUR]] self._output_path = output_path self._t_out = [0] + building.external_temperature[cte.HOUR] self.results = {} @@ -27,9 +28,9 @@ class Archetype1: heat_pump = self._hvac_system.generation_systems[0] boiler = self._hvac_system.generation_systems[1] thermal_storage = heat_pump.energy_storage_systems[0] - heat_pump.nominal_heat_output = round(0.5 * self._heating_peak_load / 3600) - heat_pump.nominal_cooling_output = round(self._cooling_peak_load / 3600) - boiler.nominal_heat_output = round(0.5 * self._heating_peak_load / 3600) + heat_pump.nominal_heat_output = round(0.5 * self._heating_peak_load) + heat_pump.nominal_cooling_output = round(self._cooling_peak_load) + boiler.nominal_heat_output = round(0.5 * self._heating_peak_load) thermal_storage.volume = round( (self._heating_peak_load * storage_factor * cte.WATTS_HOUR_TO_JULES) / (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 25)) @@ -60,7 +61,7 @@ class Archetype1: (t_sup_hp, t_tank, t_ret, m_ch, m_dis, q_hp, q_boiler, hp_cop, hp_electricity, boiler_gas, boiler_consumption, t_sup_boiler, heating_consumption) = [variables[name] for name in variable_names] - t_tank[0] = 55 + t_tank[0] = 30 dt = 3600 hp_heating_cap = hp.nominal_heat_output hp_efficiency = float(hp.heat_efficiency) diff --git a/scripts/system_simulation_models/archetype13.py b/scripts/system_simulation_models/archetype13_electric.py similarity index 89% rename from scripts/system_simulation_models/archetype13.py rename to scripts/system_simulation_models/archetype13_electric.py index 642bfca4..87b29e69 100644 --- a/scripts/system_simulation_models/archetype13.py +++ b/scripts/system_simulation_models/archetype13_electric.py @@ -22,12 +22,13 @@ class Archetype13: self._hourly_dhw_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in building.domestic_hot_water_heat_demand[cte.HOUR]] self._output_path = output_path - self._t_out = building.external_temperature[cte.HOUR] + self._t_out = [15]*8760 + # building.external_temperature[cte.HOUR] self.results = {} self.dt = 900 - def hvac_sizing(self): - storage_factor = 3 + def hvac_sizing(self,storage_factor=3): + storage_factor = storage_factor heat_pump = self._hvac_system.generation_systems[1] boiler = self._hvac_system.generation_systems[0] thermal_storage = boiler.energy_storage_systems[0] @@ -39,8 +40,8 @@ class Archetype13: (cte.WATER_HEAT_CAPACITY * cte.WATER_DENSITY * 25)) return heat_pump, boiler, thermal_storage - def dhw_sizing(self): - storage_factor = 3 + def dhw_sizing(self,storage_factor=3): + storage_factor = storage_factor dhw_hp = self._dhw_system.generation_systems[0] dhw_hp.nominal_heat_output = 0.7 * self._domestic_hot_water_peak_load dhw_hp.source_temperature = self._t_out @@ -51,7 +52,7 @@ class Archetype13: def heating_system_simulation(self): hp, boiler, tes = self.hvac_sizing() - cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + # cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) demand = [0] + [x for x in self._hourly_heating_demand for _ in range(number_of_ts)] t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] @@ -102,12 +103,13 @@ class Archetype13: t_tank_fahrenheit = 1.8 * t_tank[i + 1] + 32 t_out_fahrenheit = 1.8 * t_out[i + 1] + 32 if q_hp[i + 1] > 0: - hp_cop[i + 1] = (1 / (cop_curve_coefficients[0] + - cop_curve_coefficients[1] * t_tank_fahrenheit + - cop_curve_coefficients[2] * t_tank_fahrenheit ** 2 + - cop_curve_coefficients[3] * t_out_fahrenheit + - cop_curve_coefficients[4] * t_out_fahrenheit ** 2 + - cop_curve_coefficients[5] * t_tank_fahrenheit * t_out_fahrenheit)) * hp_efficiency + hp_cop[i + 1] =4.07 + # (1 / (cop_curve_coefficients[0] + + # cop_curve_coefficients[1] * t_tank_fahrenheit + + # cop_curve_coefficients[2] * t_tank_fahrenheit ** 2 + + # cop_curve_coefficients[3] * t_out_fahrenheit + + # cop_curve_coefficients[4] * t_out_fahrenheit ** 2 + + # cop_curve_coefficients[5] * t_tank_fahrenheit * t_out_fahrenheit)) * hp_efficiency hp_electricity[i + 1] = q_hp[i + 1] / hp_cop[i + 1] else: hp_cop[i + 1] = 0 @@ -119,7 +121,7 @@ class Archetype13: elif demand[i + 1] > 0.5 * self._heating_peak_load / self.dt: q_boiler[i + 1] = 0.5 * boiler_heating_cap boiler_energy_consumption[i + 1] = q_boiler[i + 1] / boiler_efficiency - boiler_gas_consumption[i + 1] = (q_boiler[i + 1] * self.dt) / (boiler_efficiency * cte.NATURAL_GAS_LHV) + # boiler_gas_consumption[i + 1] = (q_boiler[i + 1] * self.dt) / (boiler_efficiency * cte.NATURAL_GAS_LHV) t_sup_boiler[i + 1] = t_sup_hp[i + 1] + (q_boiler[i + 1] / (m_ch[i + 1] * cte.WATER_HEAT_CAPACITY)) # storage discharging if demand[i + 1] == 0: @@ -178,7 +180,7 @@ class Archetype13: def cooling_system_simulation(self): hp = self.hvac_sizing()[0] - eer_curve_coefficients = [float(coefficient) for coefficient in hp.cooling_efficiency_curve.coefficients] + # eer_curve_coefficients = [float(coefficient) for coefficient in hp.cooling_efficiency_curve.coefficients] cooling_efficiency = float(hp.cooling_efficiency) number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) demand = [0] + [x for x in self._hourly_cooling_demand for _ in range(number_of_ts)] @@ -216,12 +218,13 @@ class Archetype13: t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i] + 32 t_out_fahrenheit = 1.8 * t_out[i] + 32 if q_hp[i] > 0: - hp_cop[i] = (1 / (eer_curve_coefficients[0] + - eer_curve_coefficients[1] * t_sup_hp_fahrenheit + - eer_curve_coefficients[2] * t_sup_hp_fahrenheit ** 2 + - eer_curve_coefficients[3] * t_out_fahrenheit + - eer_curve_coefficients[4] * t_out_fahrenheit ** 2 + - eer_curve_coefficients[5] * t_sup_hp_fahrenheit * t_out_fahrenheit)) * cooling_efficiency / 3.41 + hp_cop[i] = 4 + # (1 / (eer_curve_coefficients[0] + + # eer_curve_coefficients[1] * t_sup_hp_fahrenheit + + # eer_curve_coefficients[2] * t_sup_hp_fahrenheit ** 2 + + # eer_curve_coefficients[3] * t_out_fahrenheit + + # eer_curve_coefficients[4] * t_out_fahrenheit ** 2 + + # eer_curve_coefficients[5] * t_sup_hp_fahrenheit * t_out_fahrenheit)) * cooling_efficiency / 3.41 hp_electricity[i] = q_hp[i] / cooling_efficiency else: hp_cop[i] = 0 @@ -251,7 +254,7 @@ class Archetype13: def dhw_system_simulation(self): hp, tes = self.dhw_sizing() - cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] + # cop_curve_coefficients = [float(coefficient) for coefficient in hp.heat_efficiency_curve.coefficients] number_of_ts = int(cte.HOUR_TO_SECONDS / self.dt) demand = [0] + [x for x in self._hourly_dhw_demand for _ in range(number_of_ts)] t_out = [0] + [x for x in self._t_out for _ in range(number_of_ts)] @@ -298,12 +301,13 @@ class Archetype13: t_sup_hp_fahrenheit = 1.8 * t_sup_hp[i] + 32 t_out_fahrenheit = 1.8 * t_out[i] + 32 if q_hp[i] > 0: - hp_cop[i] = (cop_curve_coefficients[0] + - cop_curve_coefficients[1] * t_out[i] + - cop_curve_coefficients[2] * t_out[i] ** 2 + - cop_curve_coefficients[3] * t_tank[i] + - cop_curve_coefficients[4] * t_tank[i] ** 2 + - cop_curve_coefficients[5] * t_tank[i] * t_out[i]) * float(hp.heat_efficiency) + hp_cop[i] = 3 + # (cop_curve_coefficients[0] + + # cop_curve_coefficients[1] * t_out[i] + + # cop_curve_coefficients[2] * t_out[i] ** 2 + + # cop_curve_coefficients[3] * t_tank[i] + + # cop_curve_coefficients[4] * t_tank[i] ** 2 + + # cop_curve_coefficients[5] * t_tank[i] * t_out[i]) * float(hp.heat_efficiency) hp_electricity[i] = q_hp[i] / hp_cop[i] else: hp_cop[i] = 0