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:
Saeed Ranjbar 2023-12-05 19:38:11 -05:00
parent c3f2cfb02a
commit 020190829f
5 changed files with 8837 additions and 8844 deletions

View File

@ -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'
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)
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])]
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)']

View File

@ -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):
"""

View File

@ -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, {})

View 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