Compare commits
4 Commits
ec6affa3ad
...
b560287a54
Author | SHA1 | Date | |
---|---|---|---|
|
b560287a54 | ||
|
d40e013e74 | ||
|
2d55b710b2 | ||
|
28b4e84b80 |
5
main.py
5
main.py
|
@ -12,7 +12,10 @@ import hub.helpers.constants as cte
|
|||
from hub.exports.exports_factory import ExportsFactory
|
||||
|
||||
# Specify the GeoJSON file path
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.001)
|
||||
# geojson_file = process_geojson(a=-73.5681295982132, b=45.49218262677643, c=-73.5681295982132, d=45.51218262677643,
|
||||
# e=-73.5881295982132, f=45.49218262677643,g=-73.5881295982132, h=45.51218262677643)
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
|
||||
|
||||
file_path = (Path(__file__).parent / 'input_files' / 'output_buildings.geojson')
|
||||
# Specify the output path for the PDF file
|
||||
output_path = (Path(__file__).parent / 'out_files').resolve()
|
||||
|
|
|
@ -36,6 +36,8 @@ def CityBEM_workflow(city):
|
|||
export_building_info(city, CityBEM_path,geojson_data)
|
||||
export_weather_data(city, CityBEM_path)
|
||||
export_comprehensive_building_data(city, CityBEM_path)
|
||||
export_indoor_temperature_setpoint_data(city, CityBEM_path)
|
||||
export_internal_heat_gain_data(city, CityBEM_path)
|
||||
run_CityBEM(CityBEM_path)
|
||||
def export_geometry(city, CityBEM_path):
|
||||
"""
|
||||
|
@ -65,7 +67,6 @@ def get_building_info(geojson_data, building_id):
|
|||
center = polygon.centroid
|
||||
|
||||
return function_code, (center.x, center.y)
|
||||
|
||||
return None, None
|
||||
def export_building_info(city, CityBEM_path, geojson_file):
|
||||
"""
|
||||
|
@ -121,13 +122,13 @@ def export_weather_data(city, CityBEM_path):
|
|||
|
||||
def export_comprehensive_building_data(city, CityBEM_path):
|
||||
"""
|
||||
Export all other information from buildings (both physical and thermal properties)
|
||||
Extract and export detailed individual building data from the hub to replace CityBEM input archetypes, including both physical and thermal properties.
|
||||
:param city: City object containing necessary attributes for the workflow.
|
||||
:param CityBEM_path: Path where CityBEM input and output files are stored.
|
||||
"""
|
||||
with open(CityBEM_path / 'comprehensive_building_data.csv', 'w', newline='') as textfile:
|
||||
with open(CityBEM_path / 'Input_comprehensive_building_data_CityLayer.txt', 'w') as textfile:
|
||||
writer = csv.writer(textfile, delimiter=',')
|
||||
header_row=[
|
||||
header_row="\t".join([
|
||||
#building general information
|
||||
"buildingName",
|
||||
"constructionYear",
|
||||
|
@ -144,18 +145,30 @@ def export_comprehensive_building_data(city, CityBEM_path):
|
|||
"roofExternalH",
|
||||
"roofInternalH",
|
||||
"roofUvalue",
|
||||
"roofLongWaveEmittance",
|
||||
"roofShortWaveReflectance",
|
||||
"roofDensity",
|
||||
"roofSpecificHeat",
|
||||
"roofWWR",
|
||||
#floor details
|
||||
"floorThickness",
|
||||
"floorExternalH",
|
||||
"floorInternalH",
|
||||
"floorUvalue",
|
||||
"floorLongWaveEmittance",
|
||||
"floorShortWaveReflectance",
|
||||
"floorDensity",
|
||||
"floorSpecificHeat",
|
||||
"floorWWR",
|
||||
#wall details
|
||||
"wallThickness",
|
||||
"wallExternalH",
|
||||
"wallInternalH",
|
||||
"wallUValue",
|
||||
"wallLongWaveEmittance",
|
||||
"wallShortWaveReflectance",
|
||||
"wallDensity",
|
||||
"wallSpecificHeat",
|
||||
"wallWWRNorth",
|
||||
"wallWWREast",
|
||||
"wallWWRSouth",
|
||||
|
@ -168,9 +181,8 @@ def export_comprehensive_building_data(city, CityBEM_path):
|
|||
"thermalBridgesExtraLoses",
|
||||
"infiltrationRateOff",
|
||||
"infiltrationRateOn"
|
||||
]
|
||||
writer.writerow(header_row) #write the header row
|
||||
|
||||
])
|
||||
textfile.write(header_row + "\n") #write the header row
|
||||
#extract and write comprehensive building data from the CityLayer's hub
|
||||
for building in city.buildings:
|
||||
#data should be appended based on the order of the headers.
|
||||
|
@ -206,28 +218,72 @@ def export_comprehensive_building_data(city, CityBEM_path):
|
|||
for boundary in internal_zone.thermal_zones_from_internal_zones:
|
||||
for thermal_boundary in boundary.thermal_boundaries:
|
||||
if thermal_boundary.type == "Roof":
|
||||
layers = thermal_boundary.layers #access the roof construction layers
|
||||
non_zero_layers = [layer for layer in layers if layer.thickness > 0] #filter out layers with zero thickness
|
||||
total_thickness = thermal_boundary.thickness
|
||||
if total_thickness > 0:
|
||||
weighted_density = sum(layer.thickness * layer.density for layer in non_zero_layers) / total_thickness #weighted average represneting the entire layer.
|
||||
weighted_specific_heat = sum(
|
||||
layer.thickness * layer.specific_heat for layer in non_zero_layers) / total_thickness
|
||||
else:
|
||||
weighted_specific_heat = 0 #handle the case where total_thickness is zero to avoid division by zero
|
||||
weighted_density = 0
|
||||
row_roof = [
|
||||
thermal_boundary.thickness,
|
||||
thermal_boundary.he,
|
||||
thermal_boundary.hi,
|
||||
thermal_boundary.u_value,
|
||||
thermal_boundary.external_surface.long_wave_emittance,
|
||||
thermal_boundary.external_surface.short_wave_reflectance,
|
||||
weighted_density,
|
||||
weighted_specific_heat,
|
||||
thermal_boundary.window_ratio
|
||||
]
|
||||
elif thermal_boundary.type == "Ground":
|
||||
elif thermal_boundary.type == "Ground": #ground means floor in CityBEM based on the legacy in CityBEM.
|
||||
layers = thermal_boundary.layers # access the roof construction layers
|
||||
non_zero_layers = [layer for layer in layers if layer.thickness > 0] # filter out layers with zero thickness
|
||||
total_thickness = thermal_boundary.thickness
|
||||
if total_thickness > 0:
|
||||
weighted_density = sum(
|
||||
layer.thickness * layer.density for layer in non_zero_layers) / total_thickness
|
||||
weighted_specific_heat = sum(
|
||||
layer.thickness * layer.specific_heat for layer in non_zero_layers) / total_thickness
|
||||
else:
|
||||
weighted_specific_heat = 0 # Handle the case where total_thickness is zero to avoid division by zero
|
||||
weighted_density = 0
|
||||
row_ground = [
|
||||
thermal_boundary.thickness,
|
||||
thermal_boundary.he,
|
||||
thermal_boundary.hi,
|
||||
thermal_boundary.u_value,
|
||||
thermal_boundary.external_surface.long_wave_emittance,
|
||||
thermal_boundary.external_surface.short_wave_reflectance,
|
||||
weighted_density,
|
||||
weighted_specific_heat,
|
||||
thermal_boundary.window_ratio
|
||||
]
|
||||
elif thermal_boundary.type == "Wall" and wallCount == 0:
|
||||
wallCount += 1
|
||||
wallCount += 1 #wall counter. So far, it is assumed that all the walls have a similar properties to be exported to CityBEM, except the WWR
|
||||
layers = thermal_boundary.layers # access the roof construction layers
|
||||
non_zero_layers = [layer for layer in layers if
|
||||
layer.thickness > 0] # filter out layers with zero thickness
|
||||
total_thickness = thermal_boundary.thickness
|
||||
if total_thickness > 0:
|
||||
weighted_density = sum(layer.thickness * layer.density for layer in non_zero_layers) / total_thickness
|
||||
weighted_specific_heat = sum(
|
||||
layer.thickness * layer.specific_heat for layer in non_zero_layers) / total_thickness
|
||||
else:
|
||||
weighted_specific_heat = 0 # Handle the case where total_thickness is zero to avoid division by zero
|
||||
weighted_density = 0
|
||||
row_wall = [
|
||||
thermal_boundary.thickness,
|
||||
thermal_boundary.he,
|
||||
thermal_boundary.hi,
|
||||
thermal_boundary.u_value,
|
||||
thermal_boundary.external_surface.long_wave_emittance,
|
||||
thermal_boundary.external_surface.short_wave_reflectance,
|
||||
weighted_density,
|
||||
weighted_specific_heat,
|
||||
northWWR,
|
||||
eastWWR,
|
||||
southWWR,
|
||||
|
@ -244,21 +300,88 @@ def export_comprehensive_building_data(city, CityBEM_path):
|
|||
row.append(thermalBridgesExtraLoses)
|
||||
row.append(infiltrationRateOff)
|
||||
row.append(infiltrationRateOn)
|
||||
writer.writerow(row)
|
||||
|
||||
#convert each item in row to string (if needed) and join with tabs (tab separated data)
|
||||
row_str = "\t".join(map(str, row))
|
||||
#write the final row to the text file
|
||||
textfile.write(row_str + "\n")
|
||||
print("Individual building data is exported into a file named comprehensive_building_data.txt")
|
||||
def export_indoor_temperature_setpoint_data(city, CityBEM_path):
|
||||
"""
|
||||
Extract and export individual building data on indoor temperature setpoints
|
||||
:param city: City object containing necessary attributes for the workflow.
|
||||
:param CityBEM_path: Path where CityBEM input and output files are stored.
|
||||
"""
|
||||
#open a text file in write mode (write mode removes the content if there is any)
|
||||
with open(CityBEM_path /'Input_indoor_setpoint_temperature_CityLayer.txt', 'w') as textfile:
|
||||
#iterate through each building
|
||||
for building in city.buildings:
|
||||
#write the building name
|
||||
textfile.write("building"+building.name + '\t')
|
||||
#iterate through each internal zone in the building
|
||||
for internal_zone in building.internal_zones:
|
||||
#iterate through each boundary in the internal zone
|
||||
for boundary in internal_zone.thermal_zones_from_internal_zones:
|
||||
#gather all indoor setpoint values for both cooling and heating
|
||||
indoorSetpointValues = []
|
||||
indoorSetpointValues.extend(boundary.thermal_control.cooling_set_point_schedules[0].values)#cooling on working days
|
||||
indoorSetpointValues.extend(boundary.thermal_control.cooling_set_point_schedules[1].values)#cooling on Saturday
|
||||
indoorSetpointValues.extend(boundary.thermal_control.cooling_set_point_schedules[2].values)#cooling on Sunday/holidays
|
||||
indoorSetpointValues.extend(boundary.thermal_control.heating_set_point_schedules[0].values)#heating on working days
|
||||
indoorSetpointValues.extend(boundary.thermal_control.heating_set_point_schedules[1].values)#heating on Saturday
|
||||
indoorSetpointValues.extend(boundary.thermal_control.heating_set_point_schedules[2].values)#heating on Sunday/holidays
|
||||
|
||||
#convert values to a tab-separated strings
|
||||
values_str = '\t'.join(map(str, indoorSetpointValues))
|
||||
|
||||
#write the values to the text file for this building
|
||||
textfile.write(values_str + '\n')
|
||||
|
||||
print("Indoor temperature setpoints for every building is successfully exported into a text file named Input_indoor_setpoint_temperature_CityLayer.txt")
|
||||
def export_internal_heat_gain_data(city, CityBEM_path):
|
||||
"""
|
||||
Extract and export individual building data on internal heat gains (occupant, lighting, and equipment)
|
||||
:param city: City object containing necessary attributes for the workflow.
|
||||
:param CityBEM_path: Path where CityBEM input and output files are stored.
|
||||
"""
|
||||
# open a text file in write mode (write mode removes the content if there is any)
|
||||
with open(CityBEM_path / 'Input_internal_heat_gain_CityLayer.txt', 'w') as textfile:
|
||||
# iterate through each building
|
||||
for building in city.buildings:
|
||||
# write the building name
|
||||
textfile.write("building" + building.name + '\t') # (1) building name
|
||||
# gather all internal heat gains for every building
|
||||
internalHeatGains = []
|
||||
# iterate through each internal zone in the building
|
||||
for internal_zone in building.internal_zones:
|
||||
# iterate through each internal usage in the internal zone
|
||||
for usage in internal_zone.usages:
|
||||
# iterate through internal heat gains
|
||||
for internalGain in usage.internal_gains: # order: Occupancy, Lighting, and Appliances
|
||||
internalHeatGains.append(internalGain.average_internal_gain) # (2) average_internal_gain
|
||||
internalHeatGains.append(internalGain.convective_fraction) # (3) convective_fraction
|
||||
internalHeatGains.append(internalGain.latent_fraction) # (4) latent_fraction
|
||||
internalHeatGains.append(internalGain.radiative_fraction) # (5) radiative_fraction
|
||||
internalHeatGains.extend(internalGain.schedules[0].values) # (6-29) Working day
|
||||
internalHeatGains.extend(internalGain.schedules[1].values) # (30-54) Saturday
|
||||
internalHeatGains.extend(internalGain.schedules[2].values) # (55-79)Sunday
|
||||
# convert values to a tab-separated strings
|
||||
values_str = '\t'.join(map(str, internalHeatGains))
|
||||
# write the values to the text file for this building
|
||||
textfile.write(values_str + '\n')
|
||||
print("Internal heat gains for every building is successfully exported into a text file named Input_internal_heat_gain_CityLayer.txt")
|
||||
def run_CityBEM(CityBEM_path):
|
||||
"""
|
||||
Run the CityBEM executable after all inputs are processed.
|
||||
|
||||
:param CityBEM_path: Path where CityBEM input and output files are stored.
|
||||
Run the CityBEM executable after all inputs are processed.
|
||||
:param CityBEM_path: Path where CityBEM input and output files are stored.
|
||||
"""
|
||||
try:
|
||||
print('CityBEM execution began:')
|
||||
CityBEM_exe = CityBEM_path / 'CityBEM.exe' #path to the CityBEM executable
|
||||
#check if the executable file exists
|
||||
CityBEM_exe = CityBEM_path / 'CityBEM.exe' # path to the CityBEM executable
|
||||
# check if the executable file exists
|
||||
if not CityBEM_exe.exists():
|
||||
print(f"Error: {CityBEM_exe} does not exist.")
|
||||
subprocess.run(str(CityBEM_exe), check=True, cwd=str(CityBEM_path)) #execute the CityBEM executable
|
||||
subprocess.run(str(CityBEM_exe), check=True, cwd=str(CityBEM_path)) # execute the CityBEM executable
|
||||
print("CityBEM executable has finished successfully.")
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
|
|
|
@ -4,11 +4,40 @@ from shapely import Point
|
|||
from pathlib import Path
|
||||
|
||||
|
||||
# def process_geojson(a, b, c , d, e, f, g , h):
|
||||
# selection_box = Polygon([[a, b],
|
||||
# [c, d],
|
||||
# [e, f],
|
||||
# [g, h]])
|
||||
# geojson_file = Path('./data/collinear_clean 2.geojson').resolve()
|
||||
# output_file = Path('./input_files/output_buildings.geojson').resolve()
|
||||
# buildings_in_region = []
|
||||
#
|
||||
# with open(geojson_file, 'r') as file:
|
||||
# city = json.load(file)
|
||||
# buildings = city['features']
|
||||
#
|
||||
# for building in buildings:
|
||||
# coordinates = building['geometry']['coordinates'][0]
|
||||
# building_polygon = Polygon(coordinates)
|
||||
# centroid = Point(building_polygon.centroid)
|
||||
#
|
||||
# if centroid.within(selection_box):
|
||||
# buildings_in_region.append(building)
|
||||
#
|
||||
# output_region = {"type": "FeatureCollection",
|
||||
# "features": buildings_in_region}
|
||||
#
|
||||
# with open(output_file, 'w') as file:
|
||||
# file.write(json.dumps(output_region, indent=2))
|
||||
#
|
||||
# return output_file
|
||||
|
||||
def process_geojson(x, y, diff):
|
||||
selection_box = Polygon([[x + diff, y - diff],
|
||||
[x - diff, y - diff],
|
||||
[x - diff, y + diff],
|
||||
[x + diff, y + diff]])
|
||||
selection_box = Polygon([[x+diff, y+diff],
|
||||
[x-diff, y+diff],
|
||||
[x-diff, y-diff],
|
||||
[x+diff, y-diff]])
|
||||
geojson_file = Path('./data/collinear_clean 2.geojson').resolve()
|
||||
output_file = Path('./input_files/output_buildings.geojson').resolve()
|
||||
buildings_in_region = []
|
||||
|
@ -31,4 +60,4 @@ def process_geojson(x, y, diff):
|
|||
with open(output_file, 'w') as file:
|
||||
file.write(json.dumps(output_region, indent=2))
|
||||
|
||||
return output_file
|
||||
return output_file
|
Loading…
Reference in New Issue
Block a user