diff --git a/scripts/CityBEM_run.py b/scripts/CityBEM_run.py index 2468e37c..360b2f2e 100644 --- a/scripts/CityBEM_run.py +++ b/scripts/CityBEM_run.py @@ -65,7 +65,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 +120,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 / 'comprehensive_building_data.txt', 'w') as textfile: writer = csv.writer(textfile, delimiter=',') - header_row=[ + header_row="\t".join([ #building general information "buildingName", "constructionYear", @@ -144,18 +143,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 +179,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 +216,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,8 +298,11 @@ 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 run_CityBEM(CityBEM_path): """ Run the CityBEM executable after all inputs are processed.