Compare commits
2 Commits
7ee9f03678
...
ec6affa3ad
Author | SHA1 | Date | |
---|---|---|---|
|
ec6affa3ad | ||
|
265bb1e759 |
10
main.py
10
main.py
@ -8,15 +8,14 @@ from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
import hub.helpers.constants as cte
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
import csv
|
||||
|
||||
# Specify the GeoJSON file path
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.001)
|
||||
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()
|
||||
|
||||
# Create city object from GeoJSON file
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
@ -27,9 +26,6 @@ city = GeometryFactory('geojson',
|
||||
# Enrich city data
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
ExportsFactory('obj', city, output_path).export()
|
||||
ExportsFactory('stl', city, output_path).export()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
CityBEM_workflow(city)
|
||||
#energy_plus_workflow(city)
|
||||
print('The CityBEM test workflow is done')
|
||||
CityBEM_workflow(city) #run the city using a fast City-Building Energy Model, CityBEM
|
||||
print ("test done")
|
@ -1,9 +1,10 @@
|
||||
import pandas as pd
|
||||
import sys
|
||||
import csv
|
||||
import json
|
||||
from shapely.geometry import Polygon
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from hub.imports.weather.epw_weather_parameters import EpwWeatherParameters
|
||||
|
||||
@ -23,9 +24,16 @@ def CityBEM_workflow(city):
|
||||
if not CityBEM_path.exists():
|
||||
CityBEM_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Define the path to the GeoJSON file
|
||||
file_path = Path(__file__).parent.parent / 'input_files' / 'output_buildings.geojson'
|
||||
|
||||
#load the geojson file (for now this is necessary, later, it should be removed to extract building usage type code, center lat and lon). Later, these should be added to the building class
|
||||
with open(file_path, 'r') as f:
|
||||
geojson_data = json.load(f)
|
||||
|
||||
#call functions to provide inputs for CityBEM and finally run CityBEM
|
||||
export_geometry(city, CityBEM_path)
|
||||
export_building_info(city, CityBEM_path)
|
||||
export_building_info(city, CityBEM_path,geojson_data)
|
||||
export_weather_data(city, CityBEM_path)
|
||||
export_comprehensive_building_data(city, CityBEM_path)
|
||||
run_CityBEM(CityBEM_path)
|
||||
@ -46,7 +54,20 @@ def export_geometry(city, CityBEM_path):
|
||||
CityBEMGeometryPath2.unlink()
|
||||
(CityBEM_path / hubGeometryName).rename(CityBEM_path / CityBEMGeometryPath1)
|
||||
print("CityBEM input geometry file named Input_City_scale_geometry_CityBEM.stl file has been created successfully")
|
||||
def export_building_info(city, CityBEM_path):
|
||||
def get_building_info(geojson_data, building_id):
|
||||
for feature in geojson_data['features']:
|
||||
if feature['id'] == building_id:
|
||||
function_code = feature['properties']['function']
|
||||
coordinates = feature['geometry']['coordinates'][0]
|
||||
|
||||
#calculate the center of the polygon
|
||||
polygon = Polygon(coordinates)
|
||||
center = polygon.centroid
|
||||
|
||||
return function_code, (center.x, center.y)
|
||||
|
||||
return None, None
|
||||
def export_building_info(city, CityBEM_path, geojson_file):
|
||||
"""
|
||||
Generate the input building information file for CityBEM.
|
||||
|
||||
@ -54,13 +75,13 @@ def export_building_info(city, CityBEM_path):
|
||||
:param CityBEM_path: Path where CityBEM input and output files are stored.
|
||||
"""
|
||||
buildingInfo_path = CityBEM_path / 'Input_City_scale_building_info.txt'
|
||||
montreal_to_hub_function_dict = Dictionaries().montreal_function_to_hub_function
|
||||
reverse_dict = {v: k for k, v in montreal_to_hub_function_dict.items()} #inverting the montreal_function_to_hub_function (this is not a good approach)
|
||||
with open(buildingInfo_path, "w", newline="") as textfile: #here, "w" refers to write mode. This deletes if the file exists.
|
||||
with open(buildingInfo_path, "w", newline="") as textfile: #here, "w" refers to write mode. This deletes everything inside the file if the file exists.
|
||||
writer = csv.writer(textfile, delimiter="\t") #use tab delimiter for all CityBEM inputs
|
||||
writer.writerow(["building_stl", "building_osm", "constructionYear", "codeUsageType", "centerLongitude", "centerLatitude"]) # Header
|
||||
for building in city.buildings:
|
||||
row = ["b" + building.name, "99999", str(building.year_of_construction), str(reverse_dict.get(building.function)), "-73.5688", "45.5018"]
|
||||
function_code, center_coordinates = get_building_info(geojson_file, int (building.name))
|
||||
row = ["b" + building.name, "999999", str(building.year_of_construction), str(function_code), str(center_coordinates[0]), str(center_coordinates[1])]
|
||||
#note: based on CityBEM legacy, using a number like "999999" means that the data is not known/available.
|
||||
writer.writerow(row)
|
||||
|
||||
print("CityBEM input file named Input_City_scale_building_info.txt file has been created successfully")
|
||||
@ -106,7 +127,9 @@ def export_comprehensive_building_data(city, CityBEM_path):
|
||||
"""
|
||||
with open(CityBEM_path / 'comprehensive_building_data.csv', 'w', newline='') as textfile:
|
||||
writer = csv.writer(textfile, delimiter=',')
|
||||
header_row=["buildingName",
|
||||
header_row=[
|
||||
#building general information
|
||||
"buildingName",
|
||||
"constructionYear",
|
||||
"function",
|
||||
"roofType",
|
||||
@ -115,39 +138,113 @@ def export_comprehensive_building_data(city, CityBEM_path):
|
||||
"storiesAboveGround",
|
||||
"floorArea",
|
||||
"volume",
|
||||
"totalFloorArea",
|
||||
#roof details
|
||||
"roofThickness",
|
||||
"roofExternalH",
|
||||
"roofInternalH",
|
||||
"roofUvalue",
|
||||
"roofWWR",
|
||||
#floor details
|
||||
"floorThickness",
|
||||
"floorExternalH",
|
||||
"floorInternalH",
|
||||
"floorUvalue",
|
||||
"floorWWR",
|
||||
#wall details
|
||||
"wallThickness",
|
||||
"wallExternalH",
|
||||
"wallInternalH",
|
||||
"wallUValue"
|
||||
"wallUValue",
|
||||
"wallWWRNorth",
|
||||
"wallWWREast",
|
||||
"wallWWRSouth",
|
||||
"wallWWRWest",
|
||||
#window details
|
||||
"windowOverallUValue",
|
||||
"windowGValue",
|
||||
"windowFrameRatio",
|
||||
#building thermal details
|
||||
"thermalBridgesExtraLoses",
|
||||
"infiltrationRateOff",
|
||||
"infiltrationRateOn"
|
||||
]
|
||||
writer.writerow(header_row) #write the header row
|
||||
#write comprehensive building data from the CityLayer's hub
|
||||
|
||||
#extract and write comprehensive building data from the CityLayer's hub
|
||||
for building in city.buildings:
|
||||
wallCount=0
|
||||
for wall in building.walls:
|
||||
if wallCount==0:
|
||||
for thermalBoundary in wall.associated_thermal_boundaries:
|
||||
wallThickness = thermalBoundary.thickness
|
||||
wallExternalH=thermalBoundary.he
|
||||
wallInternalH=thermalBoundary.hi
|
||||
wallUValue=thermalBoundary.u_value
|
||||
row = [
|
||||
"b" + building.name,
|
||||
building.year_of_construction,
|
||||
building.function,
|
||||
building.roof_type,
|
||||
building.max_height,
|
||||
building._storeys_above_ground,
|
||||
building.average_storey_height,
|
||||
building.floor_area,
|
||||
building.volume,
|
||||
wallThickness,
|
||||
wallExternalH,
|
||||
wallInternalH,
|
||||
wallUValue
|
||||
]
|
||||
writer.writerow(row)
|
||||
wallCount=wallCount+1
|
||||
#data should be appended based on the order of the headers.
|
||||
row=[]
|
||||
row.append("b" + building.name)
|
||||
row.append(building.year_of_construction)
|
||||
row.append(building.function)
|
||||
row.append(building.roof_type)
|
||||
row.append(building.max_height)
|
||||
row.append(building._storeys_above_ground)
|
||||
row.append(building.average_storey_height)
|
||||
row.append(building.floor_area)
|
||||
row.append(building.volume)
|
||||
# Initialize boundary rows
|
||||
row_roof = [None, None, None, None, None]
|
||||
row_ground = [None, None, None, None, None]
|
||||
row_wall = [None, None, None, None, None]
|
||||
wallCount = 0 # so far, the data for one wall represents all the walls
|
||||
for internal_zone in building.internal_zones:
|
||||
totalFloorArea = internal_zone.thermal_zones_from_internal_zones[0].total_floor_area
|
||||
row.append(totalFloorArea) #append the last item in "building general information"
|
||||
WWR = internal_zone.thermal_archetype.constructions[0].window_ratio #window to wall ratio for the walls
|
||||
northWWR = float(WWR['north'])/100. #the values from the hub is in percent. The conversion is needed.
|
||||
eastWWR = float(WWR['east'])/100.
|
||||
southWWR = float(WWR['south'])/100.
|
||||
westWWR = float(WWR['west'])/100.
|
||||
windowOverallUValue = internal_zone.thermal_archetype.constructions[0].window_overall_u_value
|
||||
windowGValue = internal_zone.thermal_archetype.constructions[0].window_g_value
|
||||
windowFrameRatio = internal_zone.thermal_archetype.constructions[0].window_frame_ratio
|
||||
thermalBridgesExtraLoses = internal_zone.thermal_archetype.extra_loses_due_to_thermal_bridges
|
||||
infiltrationRateOff = internal_zone.thermal_archetype.infiltration_rate_for_ventilation_system_off
|
||||
infiltrationRateOn = internal_zone.thermal_archetype.infiltration_rate_for_ventilation_system_on
|
||||
for boundary in internal_zone.thermal_zones_from_internal_zones:
|
||||
for thermal_boundary in boundary.thermal_boundaries:
|
||||
if thermal_boundary.type == "Roof":
|
||||
row_roof = [
|
||||
thermal_boundary.thickness,
|
||||
thermal_boundary.he,
|
||||
thermal_boundary.hi,
|
||||
thermal_boundary.u_value,
|
||||
thermal_boundary.window_ratio
|
||||
]
|
||||
elif thermal_boundary.type == "Ground":
|
||||
row_ground = [
|
||||
thermal_boundary.thickness,
|
||||
thermal_boundary.he,
|
||||
thermal_boundary.hi,
|
||||
thermal_boundary.u_value,
|
||||
thermal_boundary.window_ratio
|
||||
]
|
||||
elif thermal_boundary.type == "Wall" and wallCount == 0:
|
||||
wallCount += 1
|
||||
row_wall = [
|
||||
thermal_boundary.thickness,
|
||||
thermal_boundary.he,
|
||||
thermal_boundary.hi,
|
||||
thermal_boundary.u_value,
|
||||
northWWR,
|
||||
eastWWR,
|
||||
southWWR,
|
||||
westWWR
|
||||
]
|
||||
row.extend(row_roof)
|
||||
row.extend(row_ground)
|
||||
row.extend(row_wall)
|
||||
#append window details
|
||||
row.append(windowOverallUValue)
|
||||
row.append(windowGValue)
|
||||
row.append(windowFrameRatio)
|
||||
#append building thermal details
|
||||
row.append(thermalBridgesExtraLoses)
|
||||
row.append(infiltrationRateOff)
|
||||
row.append(infiltrationRateOn)
|
||||
writer.writerow(row)
|
||||
|
||||
def run_CityBEM(CityBEM_path):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user