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