forked from s_ranjbar/city_retrofit
The energy plus result importer for multiple buildings is created and tested. Currently, buildings are enriched with hourly values but monthly and yearly values are not working.
This commit is contained in:
parent
c3f2cfb02a
commit
020190829f
@ -12,89 +12,54 @@ import csv
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class EnergyPlusSingleBuilding:
|
||||
class EnergyPlusMultipleBuildings:
|
||||
def __init__(self, city, base_path):
|
||||
self._city = city
|
||||
self._base_path = base_path
|
||||
|
||||
@staticmethod
|
||||
def _building_energy_demands(energy_plus_output_file_path):
|
||||
def _building_energy_demands(self, energy_plus_output_file_path):
|
||||
buildings_energy_demands = {}
|
||||
|
||||
with open(Path(energy_plus_output_file_path).resolve(), 'r', encoding='utf8') as csv_file:
|
||||
csv_output = csv.reader(csv_file)
|
||||
headers = next(csv_output)
|
||||
building_energy_demands = {
|
||||
'Heating (J)': [],
|
||||
'Cooling (J)': [],
|
||||
'DHW (J)': [],
|
||||
'Appliances (J)': [],
|
||||
'Lighting (J)': []
|
||||
}
|
||||
heating_column_index = []
|
||||
cooling_column_index = []
|
||||
dhw_column_index = []
|
||||
appliance_column_index = []
|
||||
lighting_column_index = []
|
||||
for index, header in enumerate(headers):
|
||||
if "Total Heating" in header:
|
||||
heating_column_index.append(index)
|
||||
elif "Total Cooling" in header:
|
||||
cooling_column_index.append(index)
|
||||
elif "DHW" in header:
|
||||
dhw_column_index.append(index)
|
||||
elif "InteriorEquipment" in header:
|
||||
appliance_column_index.append(index)
|
||||
elif "InteriorLights" in header:
|
||||
lighting_column_index.append(index)
|
||||
csv_output = list(csv.DictReader(csv_file))
|
||||
|
||||
for line in csv_output:
|
||||
total_heating_demand = 0
|
||||
total_cooling_demand = 0
|
||||
total_dhw_demand = 0
|
||||
total_appliance_demand = 0
|
||||
total_lighting_demand = 0
|
||||
for heating_index in heating_column_index:
|
||||
total_heating_demand += float(line[heating_index])
|
||||
building_energy_demands['Heating (J)'].append(total_heating_demand)
|
||||
for cooling_index in cooling_column_index:
|
||||
total_cooling_demand += float(line[cooling_index])
|
||||
building_energy_demands['Cooling (J)'].append(total_cooling_demand)
|
||||
for dhw_index in dhw_column_index:
|
||||
total_dhw_demand += float(line[dhw_index]) * cte.WATTS_HOUR_TO_JULES
|
||||
building_energy_demands['DHW (J)'].append(total_dhw_demand)
|
||||
for appliance_index in appliance_column_index:
|
||||
total_appliance_demand += float(line[appliance_index])
|
||||
building_energy_demands['Appliances (J)'].append(total_appliance_demand)
|
||||
for lighting_index in lighting_column_index:
|
||||
total_lighting_demand += float(line[lighting_index])
|
||||
building_energy_demands['Lighting (J)'].append(total_lighting_demand)
|
||||
|
||||
return building_energy_demands
|
||||
for building in self._city.buildings:
|
||||
building_name = building.name
|
||||
buildings_energy_demands[f'Building {building_name} Heating Demand (J)'] = [
|
||||
float(
|
||||
row[f"{building_name} IDEAL LOADS AIR SYSTEM:Zone Ideal Loads Supply Air Total Heating Energy [J](Hourly)"])
|
||||
for row in csv_output
|
||||
]
|
||||
buildings_energy_demands[f'Building {building_name} Cooling Demand (J)'] = [
|
||||
float(
|
||||
row[f"{building_name} IDEAL LOADS AIR SYSTEM:Zone Ideal Loads Supply Air Total Cooling Energy [J](Hourly)"])
|
||||
for row in csv_output
|
||||
]
|
||||
buildings_energy_demands[f'Building {building_name} DHW Demand (W)'] = [
|
||||
float(row[f"DHW {building.name}:Water Use Equipment Heating Rate [W](Hourly)"])
|
||||
for row in csv_output
|
||||
]
|
||||
buildings_energy_demands[f'Building {building_name} Appliances (W)'] = [
|
||||
float(row[f"{building_name}_APPLIANCE:Other Equipment Electricity Rate [W](Hourly)"])
|
||||
for row in csv_output
|
||||
]
|
||||
buildings_energy_demands[f'Building {building_name} Lighting (W)'] = [
|
||||
float(row[f"{building_name}:Zone Lights Electricity Rate [W](Hourly)"]) for row in csv_output
|
||||
]
|
||||
return buildings_energy_demands
|
||||
|
||||
def enrich(self):
|
||||
"""
|
||||
Enrich the city by using the energy plus workflow output files (J)
|
||||
:return: None
|
||||
"""
|
||||
for building in self._city.buildings:
|
||||
file_name = f'{building.name}_out.csv'
|
||||
energy_plus_output_file_path = Path(self._base_path / file_name).resolve()
|
||||
if energy_plus_output_file_path.is_file():
|
||||
building_energy_demands = self._building_energy_demands(energy_plus_output_file_path)
|
||||
building.heating_demand[cte.HOUR] = building_energy_demands['Heating (J)']
|
||||
building.cooling_demand[cte.HOUR] = building_energy_demands['Cooling (J)']
|
||||
building.domestic_hot_water_heat_demand[cte.HOUR] = building_energy_demands['DHW (J)']
|
||||
building.appliances_electrical_demand[cte.HOUR] = building_energy_demands['Appliances (J)']
|
||||
building.lighting_electrical_demand[cte.HOUR] = building_energy_demands['Lighting (J)']
|
||||
building.heating_demand[cte.MONTH] = MonthlyValues.get_total_month(building.heating_demand[cte.HOUR])
|
||||
building.cooling_demand[cte.MONTH] = MonthlyValues.get_total_month(building.cooling_demand[cte.HOUR])
|
||||
building.domestic_hot_water_heat_demand[cte.MONTH] = (
|
||||
MonthlyValues.get_total_month(building.domestic_hot_water_heat_demand[cte.HOUR]))
|
||||
building.appliances_electrical_demand[cte.MONTH] = (
|
||||
MonthlyValues.get_total_month(building.appliances_electrical_demand[cte.HOUR]))
|
||||
building.lighting_electrical_demand[cte.MONTH] = (
|
||||
MonthlyValues.get_total_month(building.lighting_electrical_demand[cte.HOUR]))
|
||||
building.heating_demand[cte.YEAR] = [sum(building.heating_demand[cte.MONTH])]
|
||||
building.cooling_demand[cte.YEAR] = [sum(building.cooling_demand[cte.MONTH])]
|
||||
building.domestic_hot_water_heat_demand[cte.YEAR] = [sum(building.domestic_hot_water_heat_demand[cte.MONTH])]
|
||||
building.appliances_electrical_demand[cte.YEAR] = [sum(building.appliances_electrical_demand[cte.MONTH])]
|
||||
building.lighting_electrical_demand[cte.YEAR] = [sum(building.lighting_electrical_demand[cte.MONTH])]
|
||||
file_name = f'{self._city.name}_out.csv'
|
||||
energy_plus_output_file_path = Path(self._base_path / file_name).resolve()
|
||||
if energy_plus_output_file_path.is_file():
|
||||
building_energy_demands = self._building_energy_demands(energy_plus_output_file_path)
|
||||
for building in self._city.buildings:
|
||||
building.heating_demand[cte.HOUR] = building_energy_demands[f'Building {building.name} Heating Demand (J)']
|
||||
building.cooling_demand[cte.HOUR] = building_energy_demands[f'Building {building.name} Cooling Demand (J)']
|
||||
building.domestic_hot_water_heat_demand[cte.HOUR] = building_energy_demands[f'Building {building.name} DHW Demand (W)']
|
||||
building.appliances_electrical_demand[cte.HOUR] = building_energy_demands[f'Building {building.name} Appliances (W)']
|
||||
|
||||
|
@ -10,8 +10,8 @@ from pathlib import Path
|
||||
from hub.helpers.utils import validate_import_export_type
|
||||
from hub.imports.results.insel_monthly_energry_balance import InselMonthlyEnergyBalance
|
||||
from hub.imports.results.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm
|
||||
from hub.imports.results.energy_plus import EnergyPlus
|
||||
# from hub.imports.results.ep_multiple_buildings import EnergyPlusMultiple
|
||||
|
||||
from hub.imports.results.ep_multiple_buildings import EnergyPlusMultipleBuildings
|
||||
from hub.imports.results.energy_plus_single_building import EnergyPlusSingleBuilding
|
||||
|
||||
class ResultFactory:
|
||||
@ -54,11 +54,11 @@ class ResultFactory:
|
||||
"""
|
||||
EnergyPlusSingleBuilding(self._city, self._base_path).enrich()
|
||||
|
||||
# def _energy_plus_multiple(self):
|
||||
# """
|
||||
# Enrich the city with energy plus results
|
||||
# """
|
||||
# EnergyPlusMultiple(self._city, self._base_path).enrich()
|
||||
def _energy_plus_multiple_buildings(self):
|
||||
"""
|
||||
Enrich the city with energy plus results
|
||||
"""
|
||||
EnergyPlusMultipleBuildings(self._city, self._base_path).enrich()
|
||||
|
||||
def enrich(self):
|
||||
"""
|
||||
|
@ -30,11 +30,11 @@ class TestResultsImport(TestCase):
|
||||
"""
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
file = 'test.geojson'
|
||||
file = 'Citylayers_neighbours_simp2.json'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
self._city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='citygml_me',
|
||||
height_field='heightmax',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
@ -115,3 +115,25 @@ class TestResultsImport(TestCase):
|
||||
self.assertDictEqual(building.domestic_hot_water_heat_demand, {})
|
||||
self.assertDictEqual(building.lighting_electrical_demand, {})
|
||||
self.assertDictEqual(building.appliances_electrical_demand, {})
|
||||
|
||||
def test_energy_plus_multiple_buildings_results_import(self):
|
||||
ResultFactory('energy_plus_multiple_buildings', self._city, self._example_path).enrich()
|
||||
csv_output_name = f'{self._city.name}_out.csv'
|
||||
csv_output_path = (self._example_path / csv_output_name).resolve()
|
||||
if csv_output_path.is_file():
|
||||
for building in self._city.buildings:
|
||||
self.assertIsNotNone(building.heating_demand)
|
||||
self.assertIsNotNone(building.cooling_demand)
|
||||
self.assertIsNotNone(building.domestic_hot_water_heat_demand)
|
||||
self.assertIsNotNone(building.lighting_electrical_demand)
|
||||
self.assertIsNotNone(building.appliances_electrical_demand)
|
||||
total_demand = sum(building.heating_demand[cte.HOUR])
|
||||
self.assertAlmostEqual(total_demand, building.heating_demand[cte.YEAR][0], 3)
|
||||
total_demand = sum(building.heating_demand[cte.MONTH])
|
||||
self.assertEqual(total_demand, building.heating_demand[cte.YEAR][0], 3)
|
||||
# if building.name != '12':
|
||||
# self.assertDictEqual(building.heating_demand, {})
|
||||
# self.assertDictEqual(building.cooling_demand, {})
|
||||
# self.assertDictEqual(building.domestic_hot_water_heat_demand, {})
|
||||
# self.assertDictEqual(building.lighting_electrical_demand, {})
|
||||
# self.assertDictEqual(building.appliances_electrical_demand, {})
|
6
tests/tests_data/Citylayers_neighbours_simp2.json
Normal file
6
tests/tests_data/Citylayers_neighbours_simp2.json
Normal file
@ -0,0 +1,6 @@
|
||||
{"type":"FeatureCollection", "features": [
|
||||
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-73.57185265377689,45.52343504199365],[-73.57186901784087,45.52344250726594],[-73.5719186361361,45.523388576721516],[-73.57169557189309,45.52328954697509],[-73.57164717307853,45.523341318247276],[-73.57185265377689,45.52343504199365]]]},"id":86522, "properties":{"ID_UEV":"01027575","CIVIQUE_DE":" 951","CIVIQUE_FI":" 959","NOM_RUE":"rue Napoléon (MTL)","SUITE_DEBU":" ","MUNICIPALI":"50","ETAGE_HORS":3,"NOMBRE_LOG":5,"ANNEE_CONS":1927,"CODE_UTILI":"1000","LETTRE_DEB":" ","LETTRE_FIN":" ","LIBELLE_UT":"Logement","CATEGORIE_":"Régulier","MATRICULE8":"9942-16-9406-0-000-0000","SUPERFICIE":189,"SUPERFIC_1":342,"NO_ARROND_":"REM21","Shape_Leng":0.000632076842566,"OBJECTID":86522,"Join_Count":1,"TARGET_FID":86522,"feature_id":"bd64c84e-a70a-4112-915e-74b79f16c189","md_id":" ","acqtech":1360,"acqtech_en":"Lidar","acqtech_fr":"Lidar","provider":461,"provideren":"Municipal","providerfr":"Municipal","datemin":"20151124","datemax":"20151208","haccmin":2,"haccmax":2,"vaccmin":1,"vaccmax":1,"heightmin":2.03,"heightmax":16.11,"elevmin":43.98,"elevmax":46.16,"bldgarea":2049.47,"comment":"Detection of Lidar points classified as ground in the building. Détection de points Lidar classifiés sol dans le bâtiment.","OBJECTID_1":86522,"Shape_Le_1":0.000632076842566,"Shape_Ar_1":1.66656602227e-8,"OBJECTID_12":86522,"Join_Count_1":4,"TARGET_FID_1":86521,"g_objectid":"965958","g_co_mrc":"66023","g_code_mun":"66023","g_arrond":"REM21","g_anrole":"2019","g_usag_pre":"Résidentiel","g_no_lot":"1885186","g_nb_poly_":"1","g_utilisat":"1000","g_nb_logem":"5","g_nb_locau":" ","g_descript":"Unité d'évaluation","g_id_provi":"66023994216872540000000","g_sup_tota":"228.4","g_geometry":"0.000850333","g_geomet_1":"2.66017e-008","g_dat_acqu":"2020-02-12T00:00:00","g_dat_char":"2020-02-17T00:00:00","Shape_Leng_1":0.000632076842566,"Shape_Area_1":1.66656602227e-8,"Shape_Length":0.0006320773708141846,"Shape_Area":1.66656602227e-8}},
|
||||
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-73.57153144831767,45.523465428286954],[-73.57149617241038,45.523503246577604],[-73.5714876720184,45.52349934711725],[-73.57146469883673,45.52352357665177],[-73.571684848377,45.523623993152796],[-73.5717241721328,45.523584846563494],[-73.57163387210545,45.52354014666048],[-73.57165310140948,45.523520919155146],[-73.57153144831767,45.523465428286954]]]},"id":92980,"properties":{"ID_UEV":"01105693","CIVIQUE_DE":" 981","CIVIQUE_FI":" 981","NOM_RUE":"rue Napoléon (MTL)","SUITE_DEBU":" ","MUNICIPALI":"50","ETAGE_HORS":1,"NOMBRE_LOG":1,"ANNEE_CONS":1927,"CODE_UTILI":"1000","LETTRE_DEB":" ","LETTRE_FIN":" ","LIBELLE_UT":"Logement","CATEGORIE_":"Condominium","MATRICULE8":"9942-26-0726-9-001-0002","SUPERFICIE":64,"SUPERFIC_1":1097,"NO_ARROND_":"REM21","Shape_Leng":0.000653576866621,"OBJECTID":92980,"Join_Count":1,"TARGET_FID":92980,"feature_id":"bd64c84e-a70a-4112-915e-74b79f16c189","md_id":" ","acqtech":1360,"acqtech_en":"Lidar","acqtech_fr":"Lidar","provider":461,"provideren":"Municipal","providerfr":"Municipal","datemin":"20151124","datemax":"20151208","haccmin":2,"haccmax":2,"vaccmin":1,"vaccmax":1,"heightmin":2.03,"heightmax":16.11,"elevmin":43.98,"elevmax":46.16,"bldgarea":2049.47,"comment":"Detection of Lidar points classified as ground in the building. Détection de points Lidar classifiés sol dans le bâtiment.","OBJECTID_1":92980,"Shape_Le_1":0.000653576866621,"Shape_Ar_1":1.64021795264e-8,"OBJECTID_12":92980,"Join_Count_1":3,"TARGET_FID_1":92979,"g_objectid":"967849","g_co_mrc":"66023","g_code_mun":"66023","g_arrond":"REM21","g_anrole":"2019","g_usag_pre":"Résidentiel","g_no_lot":"2316950","g_nb_poly_":"1","g_utilisat":"1000","g_nb_logem":"6","g_nb_locau":" ","g_descript":"Unité d'évaluation","g_id_provi":"66023994226021950000000","g_sup_tota":"205.6","g_geometry":"0.000725388","g_geomet_1":"2.3681e-008","g_dat_acqu":"2020-02-12T00:00:00","g_dat_char":"2020-02-17T00:00:00","Shape_Leng_1":0.000653576866621,"Shape_Area_1":1.64021795264e-8,"Shape_Length":0.0006535770208011338,"Shape_Area":1.64021795264e-8}},
|
||||
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-73.57185265377689,45.52343504199365],[-73.57164717307853,45.523341318247276],[-73.57159495574257,45.523397333420235],[-73.57180091488027,45.52349127660119],[-73.57185265377689,45.52343504199365]]]},"id":146189, "properties":{"ID_UEV":"01027577","CIVIQUE_DE":" 961","CIVIQUE_FI":" 965","NOM_RUE":"rue Napoléon (MTL)","SUITE_DEBU":" ","MUNICIPALI":"50","ETAGE_HORS":3,"NOMBRE_LOG":3,"ANNEE_CONS":1927,"CODE_UTILI":"1000","LETTRE_DEB":" ","LETTRE_FIN":" ","LIBELLE_UT":"Logement","CATEGORIE_":"Régulier","MATRICULE8":"9942-16-9812-9-000-0000","SUPERFICIE":159,"SUPERFIC_1":313,"NO_ARROND_":"REM21","Shape_Leng":0.00060521313674,"OBJECTID":146189,"Join_Count":1,"TARGET_FID":146189,"feature_id":"bd64c84e-a70a-4112-915e-74b79f16c189","md_id":" ","acqtech":1360,"acqtech_en":"Lidar","acqtech_fr":"Lidar","provider":461,"provideren":"Municipal","providerfr":"Municipal","datemin":"20151124","datemax":"20151208","haccmin":2,"haccmax":2,"vaccmin":1,"vaccmax":1,"heightmin":2.03,"heightmax":16.11,"elevmin":43.98,"elevmax":46.16,"bldgarea":2049.47,"comment":"Detection of Lidar points classified as ground in the building. Détection de points Lidar classifiés sol dans le bâtiment.","OBJECTID_1":146189,"Shape_Le_1":0.00060521313674,"Shape_Ar_1":1.64233386484e-8,"OBJECTID_12":146189,"Join_Count_1":4,"TARGET_FID_1":146188,"g_objectid":"967849","g_co_mrc":"66023","g_code_mun":"66023","g_arrond":"REM21","g_anrole":"2019","g_usag_pre":"Résidentiel","g_no_lot":"2316950","g_nb_poly_":"1","g_utilisat":"1000","g_nb_logem":"6","g_nb_locau":" ","g_descript":"Unité d'évaluation","g_id_provi":"66023994226021950000000","g_sup_tota":"205.6","g_geometry":"0.000725388","g_geomet_1":"2.3681e-008","g_dat_acqu":"2020-02-12T00:00:00","g_dat_char":"2020-02-17T00:00:00","Shape_Leng_1":0.00060521313674,"Shape_Area_1":1.64233386484e-8,"Shape_Length":0.0006052125392461572,"Shape_Area":1.64233386484e-8}},
|
||||
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-73.57165310140948,45.523520919155146],[-73.57166317201774,45.52351084674825],[-73.57174737194362,45.523552647236954],[-73.5717762716576,45.523526846586776],[-73.57178620916619,45.52353250781903],[-73.57181157904108,45.523504934605114],[-73.57180091488027,45.52349127660119],[-73.57159495574257,45.523397333420235],[-73.57153144831767,45.523465428286954],[-73.57165310140948,45.523520919155146]]]},"id":156117,"properties":{"ID_UEV":"01027579","CIVIQUE_DE":" 967","CIVIQUE_FI":" 977","NOM_RUE":"rue Napoléon (MTL)","SUITE_DEBU":" ","MUNICIPALI":"50","ETAGE_HORS":3,"NOMBRE_LOG":6,"ANNEE_CONS":1927,"CODE_UTILI":"1000","LETTRE_DEB":" ","LETTRE_FIN":" ","LIBELLE_UT":"Logement","CATEGORIE_":"Régulier","MATRICULE8":"9942-26-0219-5-000-0000","SUPERFICIE":206,"SUPERFIC_1":360,"NO_ARROND_":"REM21","Shape_Leng":0.000675507023301,"OBJECTID":156117,"Join_Count":1,"TARGET_FID":156117,"feature_id":"bd64c84e-a70a-4112-915e-74b79f16c189","md_id":" ","acqtech":1360,"acqtech_en":"Lidar","acqtech_fr":"Lidar","provider":461,"provideren":"Municipal","providerfr":"Municipal","datemin":"20151124","datemax":"20151208","haccmin":2,"haccmax":2,"vaccmin":1,"vaccmax":1,"heightmin":2.03,"heightmax":16.11,"elevmin":43.98,"elevmax":46.16,"bldgarea":2049.47,"comment":"Detection of Lidar points classified as ground in the building. Détection de points Lidar classifiés sol dans le bâtiment.","OBJECTID_1":156117,"Shape_Le_1":0.000675507023301,"Shape_Ar_1":1.96911729663e-8,"OBJECTID_12":156117,"Join_Count_1":5,"TARGET_FID_1":156116,"g_objectid":"965958","g_co_mrc":"66023","g_code_mun":"66023","g_arrond":"REM21","g_anrole":"2019","g_usag_pre":"Résidentiel","g_no_lot":"1885186","g_nb_poly_":"1","g_utilisat":"1000","g_nb_logem":"5","g_nb_locau":" ","g_descript":"Unité d'évaluation","g_id_provi":"66023994216872540000000","g_sup_tota":"228.4","g_geometry":"0.000850333","g_geomet_1":"2.66017e-008","g_dat_acqu":"2020-02-12T00:00:00","g_dat_char":"2020-02-17T00:00:00","Shape_Leng_1":0.000675507023301,"Shape_Area_1":1.96911729663e-8,"Shape_Length":0.0006755075167615554,"Shape_Area":1.96911729663e-8}}
|
||||
]}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user