From ad48b4432d8e524d6eca74e812c1ea34fe9b609d Mon Sep 17 00:00:00 2001 From: s_ranjbar Date: Thu, 4 Apr 2024 13:23:32 -0400 Subject: [PATCH] ep and units are fixed --- .../__pycache__/idf.cpython-39.pyc | Bin 28012 -> 24840 bytes hub/exports/building_energy/idf.py | 96 +++--------------- .../building_energy/idf_files/Minimal.idf | 48 +++++---- main.py | 2 +- scripts/energy_system_analysis_report.py | 34 +++---- 5 files changed, 59 insertions(+), 121 deletions(-) diff --git a/hub/exports/building_energy/__pycache__/idf.cpython-39.pyc b/hub/exports/building_energy/__pycache__/idf.cpython-39.pyc index 952bb6b59cd046205fe490c11f30b30e57a5df63..bea93db2f312f0aedae91886d0dbbe51e8604243 100644 GIT binary patch delta 2910 zcmb7_dr;KZ7037d7S?4SxV#^VpvYqpP*4FMJeJ)>Py}Idl~r6;&LRuT>$i)~B|BD= zbf%-Vxye7KwmRvIX{TwX{Wa92jjbk{#2C}GO_OX=b!uX2<21&ksqHjL&-s~=Mmw1) z44?Bo=bn4+>vu2LWAM$>kmxg;4I28n_JX`CNUocpR`NSfePb|iQ zfYxIrRf2`Y1vr~niaEqGoI@1QYdkCcwOEZc`!)N(Q%8CkE?0FuuE3Sl-axTh ztW#q)()HM&>PFHwY*e+Kv>hF)cAyiRsGk#8VKdn#Y{AuJSK%6LCEJW^u`NoX1>12Q z+11#Aon+Ub3%kg+;(BzGU5guVBiS~8yMG;ae^){eZrUH`>A=m{L-9`Bf?l#N>_s2h zF5HTJWY;62pR61EaU0nUIDi4N8*vba$aZ58?ZYHIID(^OH{lqLliiFmhRF6{7$?YX z!R@$%tQU9UF0#G28~2d)VWmrBom3Ly4@$}&y;cj`l&Eor1TN)4bGkNXlny*JkB=Sn zU{L>(?^xxer2ya?;@zava6mbp{6h&IQ99D5BzRKMXWkF+l5#NXQGhp2-Cxx}0m}sZ>sRijm9s8N(#@F06;BIJGc+hJlXB0CD2t!Xo9y@_Y$S zh}2p)d`k?~Hj@5H?In0x9IR`HXT-(2T6k8>uCLXd;3}ttx84We6Q}B9y5~6Xyg1g- zYJ8gI8OB+0t6@>rGb~>qSdB4*Z)_|W@Qw8OL-I?)W=k`k*;a*B1_qj(B+=M#Azd+~ES_RmN|{-ux8tw#@=hitDyZy4zC_uQfhk zRA>4CC;d@PiWcj{9=l0;4#as!ws_2bSoa3EzA5aEB6v#-If`l34?C))3!t2L90wgw zU7ixVnhI#~-zT0BXPQc-w?O&0sTicIAaa^tm#%~Oq}h}6E+t#Fx6kD&=~x1th~3uJ z(%vS&uTJ2;mL%y0i0`y4gOlRrmKyWpll*}uI5dZ(o<+j4I!!C}q$|a%-+^dEb97Ne zORaIoB+!so@fEM~E8gO1Z`?gz7tzq`ICDrkB+0+y3goA3r!hi@zw}bslh2Z8K$rm1 zQ#8WT2+u|xZzP&XfvW!s7|5@Vz%c;LcqQqYX+5}Xa5-8q36nA90Nq*|?sg>go=Dm~ zk@R~a861gnp>3K;qgreQab=dqq3LOyG-2kX`A)P}jb=_JMofcsk;K7zTD4a0#jHv5 zA?KF&=G*n0V?GBaiANPnx*KQQMvPL#p2xwv%=2OHfzJA*FNe!(iHNn0^|R z58Cbnvs3;ne;t2eToK#Xy$HV)^&LHy7ddc0R6M$eqWPmRn6JcFf_VT*grj9%HDlb1tj@Yd`Y1ia|{DR!8TOv?j?VTqA{{ zK4KJz=^AxX2%7;FB0Ix|(R^K}QM?Kiz1-de>tq}*j89APK`oBf5^;F;odD;_^^g fN{S^(pQ<;~uUW6t$LY2D?V>!G4poXXSOot8aX~1| delta 5890 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 Dp%h$y diff --git a/hub/exports/building_energy/idf.py b/hub/exports/building_energy/idf.py index ee0471ff..cf1646e3 100644 --- a/hub/exports/building_energy/idf.py +++ b/hub/exports/building_energy/idf.py @@ -54,14 +54,6 @@ class Idf: _SIZING_PERIODS = 'SIZINGPERIOD:DESIGNDAY' _LOCATION = 'SITE:LOCATION' _SIMPLE = 'Simple' - _EQUIPMENT_CONNECTIONS = 'ZONEHVAC:EQUIPMENTCONNECTIONS' - _NODE_LIST = 'NODELIST' - _BASEBOARD = 'ZONEHVAC:BASEBOARD:CONVECTIVE:ELECTRIC' - _AIR_TERMINAL_NO_REHEAT = 'AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:NOREHEAT' - _AIR_DISTRIBUTION = 'ZONEHVAC:AIRDISTRIBUTIONUNIT' - _EQUIPMENT_LIST = 'ZONEHVAC:EQUIPMENTLIST' - _SIZING_ZONE = 'SIZING:ZONE' - _DESIGN_SPECIFICATION_OUTDOOR_AIR = 'DESIGNSPECIFICATION:OUTDOORAIR' idf_surfaces = { cte.WALL: 'wall', @@ -125,8 +117,7 @@ class Idf: if levels_of_detail.construction is None: raise AttributeError('Level of detail of construction not assigned') if levels_of_detail.construction < 2: - raise AttributeError( - f'Level of detail of construction = {levels_of_detail.construction}. Required minimum level 2') + raise AttributeError(f'Level of detail of construction = {levels_of_detail.construction}. Required minimum level 2') if levels_of_detail.usage is None: raise AttributeError('Level of detail of usage not assigned') if levels_of_detail.usage < 2: @@ -357,7 +348,7 @@ class Idf: def _add_window_construction_and_material(self, thermal_opening): for window_material in self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]: if window_material['UFactor'] == thermal_opening.overall_u_value and \ - window_material['Solar_Heat_Gain_Coefficient'] == thermal_opening.g_value: + window_material['Solar_Heat_Gain_Coefficient'] == thermal_opening.g_value: return order = str(len(self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]) + 1) @@ -390,86 +381,22 @@ class Idf: ) def _add_heating_system(self, thermal_zone, zone_name): - for air_system in self._idf.idfobjects[self._EQUIPMENT_CONNECTIONS]: + for air_system in self._idf.idfobjects[self._IDEAL_LOAD_AIR_SYSTEM]: if air_system.Zone_Name == zone_name: return thermostat = self._add_thermostat(thermal_zone) - self._idf.newidfobject(self._EQUIPMENT_CONNECTIONS, + self._idf.newidfobject(self._IDEAL_LOAD_AIR_SYSTEM, Zone_Name=zone_name, - Zone_Conditioning_Equipment_List_Name=f'{zone_name} Equipment List', - Zone_Air_Inlet_Node_or_NodeList_Name=f'{zone_name} Inlet Node List', - Zone_Air_Node_Name=f'Node 1', - Zone_Return_Air_Node_or_NodeList_Name=f'{zone_name} Return Node List') - - def _add_nodelist_system(self, thermal_zone, zone_name): - self._idf.newidfobject(self._NODE_LIST, - Name=f'{zone_name} Inlet Node List', - Node_1_Name='Node 2') - self._idf.newidfobject(self._NODE_LIST, - Name=f'{zone_name} Return Node List', - Node_1_Name='Node 3') - - def _add_baseboard_system(self, thermal_zone, zone_name): - for baseboard in self._idf.idfobjects[self._BASEBOARD]: - if baseboard.Zone_Name == zone_name: - return - self._idf.newidfobject(self._BASEBOARD, Name=f'Elec Baseboard',Availability_Schedule_Name='HVAC AVAIL') - - def _add_air_terminal_system(self, thermal_zone, zone_name): - """for air_terminal in self._idf.idfobjects[self._AIR_TERMINAL_NO_REHEAT]: - if air_terminal.Zone_Name == zone_name: - return""" - self._idf.newidfobject(self._AIR_TERMINAL_NO_REHEAT, Name=f'Diffuser', - Availability_Schedule_Name='HVAC AVAIL', - Air_Inlet_Node_Name='Node 4', - Air_Outlet_Node_Name='Node 2', - Maximum_Air_Flow_Rate='AutoSize') - - def _add_air_distribution_system(self, thermal_zone, zone_name): - for air_distribution in self._idf.idfobjects[self._AIR_DISTRIBUTION]: - if air_distribution.Zone_Name == zone_name: - return - self._idf.newidfobject(self._AIR_DISTRIBUTION, - Name='ADU Diffuser', - Air_Distribution_Unit_Outlet_Node_Name='Node 2', - Air_Terminal_Object_Type='AirTerminal:SingleDuct:ConstantVolume:NoReheat', - Air_Terminal_Name='Diffuser') - - def _add_equipment_list_system(self, thermal_zone, zone_name): - for air_distribution in self._idf.idfobjects[self._EQUIPMENT_LIST]: - if air_distribution.Zone_Name == zone_name: - return - self._idf.newidfobject(self._EQUIPMENT_LIST, - Name=f'{zone_name} Equipment List', - Load_Distribution_Scheme='SequentialLoad', - Zone_Equipment_1_Object_Type='ZoneHVAC:Baseboard:Convective:Electric', - Zone_Equipment_1_Name='Elec Baseboard', - Zone_Equipment_1_Cooling_Sequence='1', - Zone_Equipment_1_Heating_or_NoLoad_Sequence='1', - Zone_Equipment_2_Object_Type='ZoneHVAC:AirDistributionUnit', - Zone_Equipment_2_Name='ADU Diffuser', - Zone_Equipment_2_Cooling_Sequence='2', - Zone_Equipment_2_Heating_or_NoLoad_Sequence='2' - ) - - def _add_sizing_zone(self, thermal_zone, zone_name): - koa=self._idf.newidfobject(self._SIZING_ZONE, - Zone_or_ZoneList_Name=f'{zone_name}', - Zone_Cooling_Design_Supply_Air_Humidity_Ratio='0.0085', - Zone_Heating_Design_Supply_Air_Humidity_Ratio='0.008' - ) - - def _add_outdoor_air_design_specification(self, thermal_zone, zone_name): - self._idf.newidfobject(self._DESIGN_SPECIFICATION_OUTDOOR_AIR, - Name='MidriseApartment Apartment Ventilation', - Outdoor_Air_Method='Sum', - Outdoor_Air_Flow_per_Person='0.0169901079552') + System_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}', + Heating_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}', + Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}', + Template_Thermostat_Name=thermostat.Name) def _add_occupancy(self, thermal_zone, zone_name): number_of_people = thermal_zone.occupancy.occupancy_density * thermal_zone.total_floor_area fraction_radiant = 0 total_sensible = ( - thermal_zone.occupancy.sensible_radiative_internal_gain + thermal_zone.occupancy.sensible_convective_internal_gain + thermal_zone.occupancy.sensible_radiative_internal_gain + thermal_zone.occupancy.sensible_convective_internal_gain ) if total_sensible != 0: fraction_radiant = thermal_zone.occupancy.sensible_radiative_internal_gain / total_sensible @@ -626,6 +553,10 @@ class Idf: self._add_zone(thermal_zone, building.name) self._add_heating_system(thermal_zone, building.name) self._add_infiltration(thermal_zone, building.name) + self._add_ventilation(thermal_zone, building.name) + self._add_occupancy(thermal_zone, building.name) + self._add_lighting(thermal_zone, building.name) + self._add_appliances(thermal_zone, building.name) self._add_dhw(thermal_zone, building.name) if self._export_type == "Surfaces": if building.name in self._target_buildings or building.name in self._adjacent_buildings: @@ -679,6 +610,7 @@ class Idf: windows_list.append(window) for window in windows_list: self._idf.removeidfobject(window) + self._idf.saveas(str(self._output_file)) return self._idf diff --git a/hub/exports/building_energy/idf_files/Minimal.idf b/hub/exports/building_energy/idf_files/Minimal.idf index 31ebb81e..b7a9a935 100644 --- a/hub/exports/building_energy/idf_files/Minimal.idf +++ b/hub/exports/building_energy/idf_files/Minimal.idf @@ -13,7 +13,7 @@ ! HVAC: None. ! - Version,24.1; + Version,23.2; Timestep,4; @@ -122,30 +122,36 @@ No, !- Do Zone Sizing Calculation No, !- Do System Sizing Calculation No, !- Do Plant Sizing Calculation - Yes, !- Run Simulation for Sizing Periods - No, !- Run Simulation for Weather File Run Periods + No, !- Run Simulation for Sizing Periods + Yes, !- Run Simulation for Weather File Run Periods No, !- Do HVAC Sizing Simulation for Sizing Periods 1; !- Maximum Number of HVAC Sizing Simulation Passes - Output:VariableDictionary,Regular; + Output:Table:SummaryReports, AnnualBuildingUtilityPerformanceSummary, + DemandEndUseComponentsSummary, + SensibleHeatGainSummary, + InputVerificationandResultsSummary, + AdaptiveComfortSummary, + Standard62.1Summary, + ClimaticDataSummary, + EquipmentSummary, + EnvelopeSummary, + LightingSummary, + HVACSizingSummary, + SystemSummary, + ComponentSizingSummary, + OutdoorAirSummary, + ObjectCountSummary, + EndUseEnergyConsumptionOtherFuelsMonthly, + PeakEnergyEndUseOtherFuelsMonthly; - Output:Variable,*,Site Outdoor Air Drybulb Temperature,Timestep; - Output:Variable,*,Site Outdoor Air Wetbulb Temperature,Timestep; + OutputControl:Table:Style, CommaAndHTML,JtoKWH; - Output:Variable,*,Site Outdoor Air Dewpoint Temperature,Timestep; - - Output:Variable,*,Site Solar Azimuth Angle,Timestep; - - Output:Variable,*,Site Solar Altitude Angle,Timestep; - - Output:Variable,*,Site Direct Solar Radiation Rate per Area,Timestep; - - Output:Variable,*,Site Diffuse Solar Radiation Rate per Area,Timestep; - - OutputControl:Table:Style, - HTML; !- Column Separator - - Output:Table:SummaryReports, - AllSummary; !- Report 1 Name + Output:Meter,DISTRICTHEATING:Facility,hourly; + Output:Meter,DISTRICTCOOLING:Facility,hourly; + Output:Meter,InteriorEquipment:Electricity,hourly; + Output:Meter,InteriorLights:Electricity,hourly; + OutputControl:IlluminanceMap:Style, + Comma; !- Column separator \ No newline at end of file diff --git a/main.py b/main.py index cfd422e7..b2441da1 100644 --- a/main.py +++ b/main.py @@ -29,7 +29,7 @@ city = GeometryFactory('geojson', function_to_hub=Dictionaries().montreal_function_to_hub_function).city # Enrich city data ConstructionFactory('nrcan', city).enrich() -UsageFactory('comnet', city).enrich() +UsageFactory('nrcan', city).enrich() WeatherFactory('epw', city).enrich() ExportsFactory('sra', city, output_path).export() sra_path = (output_path / f'{city.name}_sra.xml').resolve() diff --git a/scripts/energy_system_analysis_report.py b/scripts/energy_system_analysis_report.py index 3eccd568..09b88482 100644 --- a/scripts/energy_system_analysis_report.py +++ b/scripts/energy_system_analysis_report.py @@ -31,18 +31,18 @@ class EnergySystemAnalysisReport: building.name, str(building.year_of_construction), building.function, - str(format(building.heating_demand[cte.YEAR][0] / 1e6, '.2f')), - str(format(building.cooling_demand[cte.YEAR][0] / 1e6, '.2f')), + str(format(building.heating_demand[cte.YEAR][0] / 3.6e9, '.2f')), + str(format(building.cooling_demand[cte.YEAR][0] / 3.6e9, '.2f')), str(format(building.domestic_hot_water_heat_demand[cte.YEAR][0] / 1e6, '.2f')), str(format( - (building.lighting_electrical_demand[cte.YEAR][0] + building.appliances_electrical_demand[cte.YEAR][0]) / 1e6, - '.2f')), + (building.lighting_electrical_demand[cte.YEAR][0] + building.appliances_electrical_demand[cte.YEAR][0]) + / 1e6, '.2f')), ] intensity_data = [ building.name, str(format(total_floor_area, '.2f')), - str(format(building.heating_demand[cte.YEAR][0] / (1e3 * total_floor_area), '.2f')), - str(format(building.cooling_demand[cte.YEAR][0] / (1e3 * total_floor_area), '.2f')), + str(format(building.heating_demand[cte.YEAR][0] / (3.6e6 * total_floor_area), '.2f')), + str(format(building.cooling_demand[cte.YEAR][0] / (3.6e6 * total_floor_area), '.2f')), str(format( (building.lighting_electrical_demand[cte.YEAR][0] + building.appliances_electrical_demand[cte.YEAR][0]) / (1e3 * total_floor_area), '.2f')) @@ -109,8 +109,8 @@ class EnergySystemAnalysisReport: plt.close() building_names = [building.name for building in self.city.buildings] - yearly_heating_demand = [building.heating_demand[cte.YEAR][0] / 1e6 for building in self.city.buildings] - yearly_cooling_demand = [building.cooling_demand[cte.YEAR][0] / 1e6 for building in self.city.buildings] + yearly_heating_demand = [building.heating_demand[cte.YEAR][0] / 3.6e9 for building in self.city.buildings] + yearly_cooling_demand = [building.cooling_demand[cte.YEAR][0] / 3.6e9 for building in self.city.buildings] yearly_dhw_demand = [building.domestic_hot_water_heat_demand[cte.YEAR][0] / 1e6 for building in self.city.buildings] yearly_electricity_demand = [(building.lighting_electrical_demand[cte.YEAR][0] + @@ -139,14 +139,14 @@ class EnergySystemAnalysisReport: axs[0].bar(months, maximum_monthly_heating_load, color='red') # Plot on the first subplot axs[0].set_title('Maximum Monthly Heating Load') axs[0].set_xlabel('Month') - axs[0].set_ylabel('Load (kW)') + axs[0].set_ylabel('Load (kWh)') axs[0].tick_params(axis='x', rotation=45) # Plot maximum monthly cooling load axs[1].bar(months, maximum_monthly_cooling_load, color='blue') # Plot on the second subplot axs[1].set_title('Maximum Monthly Cooling Load') axs[1].set_xlabel('Month') - axs[1].set_ylabel('Load (kW)') + axs[1].set_ylabel('Load (kWh)') axs[1].tick_params(axis='x', rotation=45) plt.tight_layout() # Adjust layout to prevent overlapping @@ -156,8 +156,8 @@ class EnergySystemAnalysisReport: def load_duration_curves(self): save_directory = self.output_path for building in self.city.buildings: - heating_demand = [demand / 1000 for demand in building.heating_demand[cte.HOUR]] - cooling_demand = [demand / 1000 for demand in building.cooling_demand[cte.HOUR]] + heating_demand = [demand / 3.6e6 for demand in building.heating_demand[cte.HOUR]] + cooling_demand = [demand / 3.6e6 for demand in building.cooling_demand[cte.HOUR]] heating_demand_sorted = sorted(heating_demand, reverse=True) cooling_demand_sorted = sorted(cooling_demand, reverse=True) @@ -169,7 +169,7 @@ class EnergySystemAnalysisReport: # Plot sorted heating demand axs[0].plot(heating_demand_sorted, color='red', linewidth=2, label='Heating Demand') axs[0].set_xlabel('Hour', fontsize=14) - axs[0].set_ylabel('Heating Demand', fontsize=14) + axs[0].set_ylabel('Heating Demand (kWh)', fontsize=14) axs[0].set_title('Heating Load Duration Curve', fontsize=16) axs[0].grid(True) axs[0].legend(loc='upper right', fontsize=12) @@ -177,7 +177,7 @@ class EnergySystemAnalysisReport: # Plot sorted cooling demand axs[1].plot(cooling_demand_sorted, color='blue', linewidth=2, label='Cooling Demand') axs[1].set_xlabel('Hour', fontsize=14) - axs[1].set_ylabel('Cooling Demand', fontsize=14) + axs[1].set_ylabel('Cooling Demand (kWh)', fontsize=14) axs[1].set_title('Cooling Load Duration Curve', fontsize=16) axs[1].grid(True) axs[1].legend(loc='upper right', fontsize=12) @@ -204,7 +204,7 @@ class EnergySystemAnalysisReport: cooling_system = "-" dhw = "-" electricity = "Grid" - hvac_ec = format((building.heating_consumption[cte.YEAR][0] + building.cooling_consumption[cte.YEAR][0]) / 1e6, + hvac_ec = format((building.heating_consumption[cte.YEAR][0] + building.cooling_consumption[cte.YEAR][0]) / 3.6e9, '.2f') dhw_ec = format(building.domestic_hot_water_consumption[cte.YEAR][0] / 1e6, '.2f') on_site_generation = "-" @@ -258,11 +258,11 @@ class EnergySystemAnalysisReport: for generation_system in energy_system.generation_systems: consumption = 0 if demand_type == cte.HEATING: - consumption = building.heating_consumption[cte.YEAR][0] / 1e6 + consumption = building.heating_consumption[cte.YEAR][0] / 3.6e9 elif demand_type == cte.DOMESTIC_HOT_WATER: consumption = building.domestic_hot_water_consumption[cte.YEAR][0] / 1e6 elif demand_type == cte.COOLING: - consumption = building.cooling_consumption[cte.YEAR][0] / 1e6 + consumption = building.cooling_consumption[cte.YEAR][0] / 3.6e9 if generation_system.fuel_type == cte.ELECTRICITY: fuel_breakdown[demand_type]["Electricity"] += consumption