Merge branch 'main' into idf_lights
# Conflicts: # hub/exports/building_energy/idf.py # hub/unittests/test_exports.py
This commit is contained in:
commit
648548ea2c
|
@ -54,35 +54,38 @@ class MontrealCustomCatalog(Catalog):
|
|||
def _get_capital_costs(self, entry):
|
||||
general_chapters = []
|
||||
chapters_titles = CostHelper().chapters_in_lod1
|
||||
shell = entry['B_shell']
|
||||
items_list = []
|
||||
item_type = 'B10_superstructure'
|
||||
item_description = self._item_with_refurbishment_values(entry, item_type)
|
||||
item_description = self._item_with_refurbishment_values(shell, item_type)
|
||||
items_list.append(item_description)
|
||||
for item in entry['B20_envelope']:
|
||||
for item in shell['B20_envelope']:
|
||||
item_type = item
|
||||
item_description = self._item_with_refurbishment_values(entry['B20_envelope'], item_type)
|
||||
item_description = self._item_with_refurbishment_values(shell['B20_envelope'], item_type)
|
||||
items_list.append(item_description)
|
||||
item_type = 'B30_roofing'
|
||||
item_description = self._item_with_refurbishment_values(entry, item_type)
|
||||
item_type = 'B3010_opaque_roof'
|
||||
item_description = self._item_with_refurbishment_values(shell['B30_roofing'], item_type)
|
||||
items_list.append(item_description)
|
||||
general_chapters.append(Chapter('B_shell', items_list))
|
||||
|
||||
items_list = []
|
||||
item_type = 'D301010_photovoltaic_system'
|
||||
item_description = self._item_with_threesome(entry['D30_hvac']['D3010_energy_supply'], item_type)
|
||||
services = entry['D_services']
|
||||
item_description = self._item_with_threesome(services['D30_hvac']['D3010_energy_supply'], item_type)
|
||||
items_list.append(item_description)
|
||||
item_type_list = ['D3020_heat_generating_systems', 'D3030_cooling_generation_systems', 'D3040_distribution_systems',
|
||||
'D3080_other_hvac_ahu']
|
||||
for item_type in item_type_list:
|
||||
item_description = self._item_with_threesome(entry['D30_hvac'], item_type)
|
||||
item_description = self._item_with_threesome(services['D30_hvac'], item_type)
|
||||
items_list.append(item_description)
|
||||
item_type = 'D5020lighting_and_branch_wiring'
|
||||
item_description = self._item_with_threesome(entry['D50_electrical'], item_type)
|
||||
item_type = 'D5020_lighting_and_branch_wiring'
|
||||
item_description = self._item_with_threesome(services['D50_electrical'], item_type)
|
||||
items_list.append(item_description)
|
||||
general_chapters.append(Chapter('D_services', items_list))
|
||||
|
||||
design_allowance = float(entry['Z_allowances_overhead_profit']['Z10_design_allowance']['#text']) / 100
|
||||
overhead_and_profit = float(entry['Z_allowances_overhead_profit']['Z10_overhead_and_profit']['#text']) / 100
|
||||
allowances = entry['Z_allowances_overhead_profit']
|
||||
design_allowance = float(allowances['Z10_design_allowance']['#text']) / 100
|
||||
overhead_and_profit = float(allowances['Z20_overhead_profit']['#text']) / 100
|
||||
_capital_cost = CapitalCost(general_chapters, design_allowance, overhead_and_profit)
|
||||
|
||||
return _capital_cost
|
||||
|
@ -90,17 +93,17 @@ class MontrealCustomCatalog(Catalog):
|
|||
@staticmethod
|
||||
def _get_operational_costs(entry):
|
||||
fuels = []
|
||||
for item in entry['fuels']:
|
||||
fuel_type = item['fuel']['@fuel_type']
|
||||
fuel_variable = float(entry['fuel']['variable']['#text'])
|
||||
fuel_variable_units = float(entry['fuel']['variable']['@cost_unit'])
|
||||
for item in entry['fuels']['fuel']:
|
||||
fuel_type = item['@fuel_type']
|
||||
fuel_variable = float(item['variable']['#text'])
|
||||
fuel_variable_units = item['variable']['@cost_unit']
|
||||
fuel_fixed_monthly = None
|
||||
fuel_fixed_peak = None
|
||||
if fuel_type == 'electricity':
|
||||
fuel_fixed_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text'])
|
||||
fuel_fixed_peak = float(entry['fuel']['fixed']['fixed_power']['#text']) / 1000
|
||||
fuel_fixed_monthly = float(item['fixed_monthly']['#text'])
|
||||
fuel_fixed_peak = float(item['fixed_power']['#text']) / 1000
|
||||
elif fuel_type == 'gas':
|
||||
fuel_fixed_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text'])
|
||||
fuel_fixed_monthly = float(item['fixed_monthly']['#text'])
|
||||
fuel = Fuel(fuel_type,
|
||||
fixed_monthly=fuel_fixed_monthly,
|
||||
fixed_power=fuel_fixed_peak,
|
||||
|
@ -110,7 +113,7 @@ class MontrealCustomCatalog(Catalog):
|
|||
heating_equipment_maintenance = float(entry['maintenance']['heating_equipment']['#text']) / 1000
|
||||
cooling_equipment_maintenance = float(entry['maintenance']['cooling_equipment']['#text']) / 1000
|
||||
photovoltaic_system_maintenance = float(entry['maintenance']['photovoltaic_system']['#text'])
|
||||
co2_emissions = float(entry['CO2_cost']['#text'])
|
||||
co2_emissions = float(entry['co2_cost']['#text'])
|
||||
_operational_cost = OperationalCost(fuels,
|
||||
heating_equipment_maintenance,
|
||||
cooling_equipment_maintenance,
|
||||
|
@ -127,14 +130,13 @@ class MontrealCustomCatalog(Catalog):
|
|||
country = archetype['@country']
|
||||
lod = float(archetype['@lod'])
|
||||
currency = archetype['currency']
|
||||
print(currency)
|
||||
capital_cost = self._get_capital_costs(archetype['capital_cost'])
|
||||
operational_cost = self._get_operational_costs(archetype['operational_cost'])
|
||||
end_of_life_cost = float(archetype['end_of_life_cost']['#text'])
|
||||
construction = float(archetype['incomes']['subsidies']['construction_subsidy']['#text'])
|
||||
hvac = float(archetype['incomes']['subsidies']['hvac_subsidy']['#text'])
|
||||
photovoltaic_system = float(archetype['incomes']['subsidies']['photovoltaic_subsidy']['#text'])
|
||||
electricity_exports = float(archetype['incomes']['energy_exports']['electricity']['#text']) / 1000 / 3600
|
||||
construction = float(archetype['incomes']['subsidies']['construction']['#text'])
|
||||
hvac = float(archetype['incomes']['subsidies']['hvac']['#text'])
|
||||
photovoltaic_system = float(archetype['incomes']['subsidies']['photovoltaic']['#text'])
|
||||
electricity_exports = float(archetype['incomes']['electricity_export']['#text']) / 1000 / 3600
|
||||
reduction_tax = float(archetype['incomes']['tax_reduction']['#text']) / 100
|
||||
income = Income(construction_subsidy=construction,
|
||||
hvac_subsidy=hvac,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<capital_cost>
|
||||
<B_shell>
|
||||
<B10_superstructure>
|
||||
<refurbishment_cost_basement cost_unit="currency/m2"> 0 </refurbishment_cost_basement>
|
||||
<refurbishment_cost cost_unit="currency/m2"> 0 </refurbishment_cost>
|
||||
</B10_superstructure>
|
||||
<B20_envelope>
|
||||
<B2010_opaque_walls>
|
||||
|
@ -24,7 +24,7 @@
|
|||
<D30_hvac>
|
||||
<D3010_energy_supply>
|
||||
<D301010_photovoltaic_system>
|
||||
<initial_investment cost_unit="currency/m2"> 800 </initial_investment>
|
||||
<investment_cost cost_unit="currency/m2"> 800 </investment_cost>
|
||||
<reposition cost_unit="currency/m2"> 800 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D301010_photovoltaic_system>
|
||||
|
@ -51,16 +51,16 @@
|
|||
</D3080_other_hvac_ahu>
|
||||
</D30_hvac>
|
||||
<D50_electrical>
|
||||
<D5020lighting_and_branch_wiring>
|
||||
<refurbishment_cost cost_unit="currency/kW"> 139 </refurbishment_cost>
|
||||
<D5020_lighting_and_branch_wiring>
|
||||
<investment_cost cost_unit="currency/kW"> 139 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 139 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</D5020lighting_and_branch_wiring>
|
||||
</D5020_lighting_and_branch_wiring>
|
||||
</D50_electrical>
|
||||
</D_services>
|
||||
<Z_allowances_overhead_profit>
|
||||
<Z10_design_allowance cost_unit="%"> 2.5 </Z10_design_allowance>
|
||||
<Z10_overhead_and_profit cost_unit="%"> 14 </Z10_overhead_and_profit>
|
||||
<Z20_overhead_profit cost_unit="%"> 14 </Z20_overhead_profit>
|
||||
</Z_allowances_overhead_profit>
|
||||
</capital_cost>
|
||||
<operational_cost>
|
||||
|
@ -81,23 +81,21 @@
|
|||
<variable cost_unit="currency/kg"> 0.09 </variable>
|
||||
</fuel>
|
||||
</fuels>
|
||||
<maintenances>
|
||||
<maintenance type="heating_equipment" cost_unit="currency/kW">40</maintenance>
|
||||
<maintenance type="cooling_equipment" cost_unit="currency/kW">40</maintenance>
|
||||
<maintenance type="photovoltaic_system" cost_unit="currency/m2">1</maintenance>
|
||||
</maintenances>
|
||||
<maintenance>
|
||||
<heating_equipment cost_unit="currency/kW">40</heating_equipment>
|
||||
<cooling_equipment cost_unit="currency/kW">40</cooling_equipment>
|
||||
<photovoltaic_system cost_unit="currency/m2">1</photovoltaic_system>
|
||||
</maintenance>
|
||||
<co2_cost cost_unit="currency/kgCO2"> 30 </co2_cost>
|
||||
</operational_cost>
|
||||
<end_of_life_cost cost_unit="currency/m2"> 6.3 </end_of_life_cost>
|
||||
<incomes>
|
||||
<subsidies>
|
||||
<subsidy type="construction" cost_unit="%">2</subsidy>
|
||||
<subsidy type="hvac" cost_unit="%">1.5</subsidy>
|
||||
<subsidy type="photovoltaic" cost_unit="%">3.6</subsidy>
|
||||
<subsidies>
|
||||
<construction cost_unit="%">2</construction>
|
||||
<hvac cost_unit="%">1.5</hvac>
|
||||
<photovoltaic cost_unit="%">3.6</photovoltaic>
|
||||
</subsidies>
|
||||
<energy_exports>
|
||||
<energy_export type="electricity" cost_unit="currency/kWh">0</energy_export>
|
||||
</energy_exports>
|
||||
<electricity_export cost_unit="currency/kWh">0</electricity_export>
|
||||
<tax_reduction cost_unit="%">2</tax_reduction>
|
||||
</incomes>
|
||||
</archetype>
|
||||
|
@ -106,7 +104,7 @@
|
|||
<capital_cost>
|
||||
<B_shell>
|
||||
<B10_superstructure>
|
||||
<refurbishment_cost_basement cost_unit="currency/m2"> 0 </refurbishment_cost_basement>
|
||||
<refurbishment_cost cost_unit="currency/m2"> 0 </refurbishment_cost>
|
||||
</B10_superstructure>
|
||||
<B20_envelope>
|
||||
<B2010_opaque_walls>
|
||||
|
@ -126,7 +124,7 @@
|
|||
<D30_hvac>
|
||||
<D3010_energy_supply>
|
||||
<D301010_photovoltaic_system>
|
||||
<initial_investment cost_unit="currency/m2"> 800 </initial_investment>
|
||||
<investment_cost cost_unit="currency/m2"> 800 </investment_cost>
|
||||
<reposition cost_unit="currency/m2"> 800 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D301010_photovoltaic_system>
|
||||
|
@ -142,7 +140,7 @@
|
|||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3030_cooling_generation_systems>
|
||||
<D3040_distribution_systems>
|
||||
<refurbishment_cost cost_unit="currency/m2"> 0 </refurbishment_cost>
|
||||
<investment_cost cost_unit="currency/m2"> 0 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3040_distribution_systems>
|
||||
|
@ -154,7 +152,7 @@
|
|||
</D30_hvac>
|
||||
<D50_electrical>
|
||||
<D5020_lighting_and_branch_wiring>
|
||||
<refurbishment_cost cost_unit="currency/kW"> 139 </refurbishment_cost>
|
||||
<investment_cost cost_unit="currency/kW"> 139 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 139 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</D5020_lighting_and_branch_wiring>
|
||||
|
@ -166,38 +164,38 @@
|
|||
</Z_allowances_overhead_profit>
|
||||
</capital_cost>
|
||||
<operational_cost>
|
||||
<fuel fuel_type="electricity">
|
||||
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
|
||||
<fixed_power cost_unit="currency/(month*kW)"> 0 </fixed_power>
|
||||
<variable cost_unit="currency/kWh"> 0.075 </variable>
|
||||
</fuel>
|
||||
<fuel fuel_type="gas">
|
||||
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
|
||||
<variable cost_unit="currency/m3"> 0.640 </variable>
|
||||
</fuel>
|
||||
<fuel fuel_type="diesel">
|
||||
<variable cost_unit="currency/l"> 1.2 </variable>
|
||||
</fuel>
|
||||
<fuel fuel_type="biomass">
|
||||
<variable cost_unit="currency/kg"> 0.09 </variable>
|
||||
</fuel>
|
||||
<maintenances>
|
||||
<maintenance type="heating_equipment" cost_unit="currency/kW">40</maintenance>
|
||||
<maintenance type="cooling_equipment" cost_unit="currency/kW">40</maintenance>
|
||||
<maintenance type="photovoltaic_system" cost_unit="currency/m2">1</maintenance>
|
||||
</maintenances>
|
||||
<CO2_cost cost_unit="currency/kgCO2"> 30 </CO2_cost>
|
||||
<fuels>
|
||||
<fuel fuel_type="electricity">
|
||||
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
|
||||
<fixed_power cost_unit="currency/(month*kW)"> 0 </fixed_power>
|
||||
<variable cost_unit="currency/kWh"> 0.075 </variable>
|
||||
</fuel>
|
||||
<fuel fuel_type="gas">
|
||||
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
|
||||
<variable cost_unit="currency/m3"> 0.640 </variable>
|
||||
</fuel>
|
||||
<fuel fuel_type="diesel">
|
||||
<variable cost_unit="currency/l"> 1.2 </variable>
|
||||
</fuel>
|
||||
<fuel fuel_type="biomass">
|
||||
<variable cost_unit="currency/kg"> 0.09 </variable>
|
||||
</fuel>
|
||||
</fuels>
|
||||
<maintenance>
|
||||
<heating_equipment cost_unit="currency/kW">40</heating_equipment>
|
||||
<cooling_equipment cost_unit="currency/kW">40</cooling_equipment>
|
||||
<photovoltaic_system cost_unit="currency/m2">1</photovoltaic_system>
|
||||
</maintenance>
|
||||
<co2_cost cost_unit="currency/kgCO2"> 30 </co2_cost>
|
||||
</operational_cost>
|
||||
<end_of_life_cost cost_unit="currency/m2"> 6.3 </end_of_life_cost>
|
||||
<incomes>
|
||||
<subsidies>
|
||||
<subsidy type="construction" cost_unit="%">2</subsidy>
|
||||
<subsidy type="hvac" cost_unit="%">1.5</subsidy>
|
||||
<subsidy type="photovoltaic" cost_unit="%">3.6</subsidy>
|
||||
<subsidies>
|
||||
<construction cost_unit="%">2</construction>
|
||||
<hvac cost_unit="%">1.5</hvac>
|
||||
<photovoltaic cost_unit="%">3.6</photovoltaic>
|
||||
</subsidies>
|
||||
<energy_exports>
|
||||
<energy_export type="electricity" cost_unit="currency/kWh">0</energy_export>
|
||||
</energy_exports>
|
||||
<electricity_export cost_unit="currency/kWh">0</electricity_export>
|
||||
<tax_reduction cost_unit="%">2</tax_reduction>
|
||||
</incomes>
|
||||
</archetype>
|
||||
|
|
|
@ -189,6 +189,8 @@ class Idf:
|
|||
|
||||
def _add_infiltration_schedules(self, thermal_zone):
|
||||
_infiltration_schedules = []
|
||||
if thermal_zone.thermal_control is None:
|
||||
return
|
||||
for hvac_availability_schedule in thermal_zone.thermal_control.hvac_availability_schedules:
|
||||
_schedule = Schedule()
|
||||
_schedule.type = cte.INFILTRATION
|
||||
|
@ -322,7 +324,6 @@ class Idf:
|
|||
|
||||
def _add_occupancy(self, thermal_zone, zone_name):
|
||||
number_of_people = thermal_zone.occupancy.occupancy_density * thermal_zone.total_floor_area
|
||||
print(thermal_zone.occupancy.occupancy_density)
|
||||
fraction_radiant = 0
|
||||
total_sensible = thermal_zone.occupancy.sensible_radiative_internal_gain + \
|
||||
thermal_zone.occupancy.sensible_convective_internal_gain
|
||||
|
@ -390,10 +391,13 @@ class Idf:
|
|||
for zone in self._idf.idfobjects["ZONE"]:
|
||||
if zone.Name == f'{zone_name}_infiltration':
|
||||
return
|
||||
schedule = f'Infiltration schedules {thermal_zone.usage_name}'
|
||||
if schedule not in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
||||
return
|
||||
self._idf.newidfobject(self._INFILTRATION,
|
||||
Name=f'{zone_name}_infiltration',
|
||||
Zone_or_ZoneList_Name=zone_name,
|
||||
Schedule_Name=f'Infiltration schedules {thermal_zone.usage_name}',
|
||||
Schedule_Name=schedule,
|
||||
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
||||
Air_Changes_per_Hour=thermal_zone.mechanical_air_change
|
||||
)
|
||||
|
@ -428,6 +432,8 @@ class Idf:
|
|||
self._lod = self._city.level_of_detail.geometry
|
||||
for building in self._city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
if internal_zone.thermal_zones is None:
|
||||
continue
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self._add_construction(thermal_boundary)
|
||||
|
@ -456,7 +462,10 @@ class Idf:
|
|||
|
||||
if self._export_type == "Surfaces":
|
||||
if building.name in self._target_buildings or building.name in self._adjacent_buildings:
|
||||
self._add_surfaces(building, building.name)
|
||||
if building.internal_zones[0].thermal_zones is not None:
|
||||
self._add_surfaces(building, building.name)
|
||||
else:
|
||||
self._add_pure_geometry(building, building.name)
|
||||
else:
|
||||
self._add_shading(building)
|
||||
else:
|
||||
|
@ -540,7 +549,34 @@ class Idf:
|
|||
Diffuse_Solar_Reflectance_of_Unglazed_Part_of_Shading_Surface=solar_reflectance,
|
||||
Fraction_of_Shading_Surface_That_Is_Glazed=0)
|
||||
|
||||
# todo: Add properties for that name
|
||||
def _add_pure_geometry(self, building, zone_name):
|
||||
for surface in building.surfaces:
|
||||
idf_surface_type = self.idf_surfaces[surface.type]
|
||||
outside_boundary_condition = 'Outdoors'
|
||||
sun_exposure = 'SunExposed'
|
||||
wind_exposure = 'WindExposed'
|
||||
if surface.type == cte.GROUND:
|
||||
outside_boundary_condition = 'Ground'
|
||||
sun_exposure = 'NoSun'
|
||||
wind_exposure = 'NoWind'
|
||||
idf_surface = self._idf.newidfobject(self._SURFACE, Name=f'{surface.name}',
|
||||
Surface_Type=idf_surface_type,
|
||||
Zone_Name=zone_name,
|
||||
Outside_Boundary_Condition=outside_boundary_condition,
|
||||
Sun_Exposure=sun_exposure,
|
||||
Wind_Exposure=wind_exposure)
|
||||
coordinates = self._matrix_to_list(surface.solid_polygon.coordinates,
|
||||
self._city.lower_corner)
|
||||
idf_surface.setcoords(coordinates)
|
||||
if self._lod >= 3:
|
||||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
for boundary in thermal_zone.thermal_boundaries:
|
||||
self._add_windows_by_vertices(boundary)
|
||||
else:
|
||||
# idf only allows setting wwr for external walls
|
||||
wwr = 0
|
||||
self._idf.set_wwr(wwr)
|
||||
|
||||
def _add_surfaces(self, building, zone_name):
|
||||
for internal_zone in building.internal_zones:
|
||||
|
@ -567,7 +603,6 @@ class Idf:
|
|||
Wind_Exposure=wind_exposure)
|
||||
coordinates = self._matrix_to_list(boundary.parent_surface.solid_polygon.coordinates,
|
||||
self._city.lower_corner)
|
||||
|
||||
surface.setcoords(coordinates)
|
||||
|
||||
if self._lod >= 3:
|
||||
|
|
|
@ -173,7 +173,8 @@ class InselMonthlyEnergyBalance(Insel):
|
|||
type_code = _CONSTRUCTION_CODE[thermal_boundary.type]
|
||||
wall_area = thermal_boundary.opaque_area * (1 + thermal_boundary.window_ratio)
|
||||
if thermal_boundary.type == cte.WALL:
|
||||
wall_area = wall_area * (1 - thermal_boundary.parent_surface.percentage_shared)
|
||||
if thermal_boundary.parent_surface.percentage_shared is not None:
|
||||
wall_area = wall_area * (1 - thermal_boundary.parent_surface.percentage_shared)
|
||||
window_area = wall_area * thermal_boundary.window_ratio
|
||||
|
||||
parameters.append(type_code)
|
||||
|
|
|
@ -8,8 +8,12 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
|||
# universal constants
|
||||
|
||||
KELVIN = 273.15
|
||||
WATER_DENSITY = 1000
|
||||
WATER_HEAT_CAPACITY = 4182
|
||||
WATER_DENSITY = 1000 # kg/m3
|
||||
WATER_HEAT_CAPACITY = 4182 # J/kgK
|
||||
|
||||
AIR_DENSITY = 1.293 # kg/m3
|
||||
AIR_HEAT_CAPACITY = 1005.2 # J/kgK
|
||||
|
||||
|
||||
# converters
|
||||
HOUR_TO_MINUTES = 60
|
||||
|
@ -44,6 +48,24 @@ WEEK_DAYS = 'Weekdays'
|
|||
WEEK_ENDS = 'Weekends'
|
||||
ALL_DAYS = 'Alldays'
|
||||
|
||||
DAYS_A_MONTH = {'monday': [5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 5],
|
||||
'tuesday': [5, 4, 4, 4, 5, 4, 5, 4, 4, 5, 4, 4],
|
||||
'wednesday': [5, 4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4],
|
||||
'thursday': [4, 4, 5, 4, 5, 4, 4, 5, 4, 4, 5, 4],
|
||||
'friday': [4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5, 4],
|
||||
'saturday': [4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5],
|
||||
'sunday': [4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5],
|
||||
'holiday': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
|
||||
|
||||
DAYS_A_YEAR = {'monday': 53,
|
||||
'tuesday': 52,
|
||||
'wednesday': 52,
|
||||
'thursday': 52,
|
||||
'friday': 52,
|
||||
'saturday': 52,
|
||||
'sunday': 52,
|
||||
'holiday': 0}
|
||||
|
||||
# data types
|
||||
ANY_NUMBER = 'any_number'
|
||||
FRACTION = 'fraction'
|
||||
|
|
|
@ -36,21 +36,21 @@ class HubUsageToNrcanUsage:
|
|||
cte.LABORATORY_AND_RESEARCH_CENTER: 'School/university',
|
||||
cte.STAND_ALONE_RETAIL: 'Retail area',
|
||||
cte.HOSPITAL: 'Hospital',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'Health-care clinic',
|
||||
cte.HEALTH_CARE: 'Health-care clinic',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Health-care clinic',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'Health care clinic',
|
||||
cte.HEALTH_CARE: 'Health care clinic',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Health care clinic',
|
||||
cte.COMMERCIAL: 'Retail area',
|
||||
cte.STRIP_MALL: 'Retail area',
|
||||
cte.SUPERMARKET: 'Retail area',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'Retail area',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'Retail area',
|
||||
cte.RESTAURANT: 'Dining - bar/lounge',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'Dining - cafeteria',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'Dining - bar/lounge',
|
||||
cte.HOTEL: 'Hotel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'Motel',
|
||||
cte.SMALL_HOTEL: 'Motel',
|
||||
cte.LARGE_HOTEL: 'Hotel',
|
||||
cte.RESTAURANT: 'Dining - bar lounge/leisure',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'Dining - cafeteria/fast food',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'Dining - bar lounge/leisure',
|
||||
cte.HOTEL: 'Hotel/Motel',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'Hotel/Motel',
|
||||
cte.SMALL_HOTEL: 'Hotel/Motel',
|
||||
cte.LARGE_HOTEL: 'Hotel/Motel',
|
||||
cte.DORMITORY: 'Dormitory',
|
||||
cte.EVENT_LOCATION: 'Convention centre',
|
||||
cte.CONVENTION_CENTER: 'Convention centre',
|
||||
|
@ -59,17 +59,17 @@ class HubUsageToNrcanUsage:
|
|||
cte.INDUSTRY: 'Manufacturing facility',
|
||||
cte.WORKSHOP: 'Workshop',
|
||||
cte.WAREHOUSE: 'Warehouse',
|
||||
cte.WAREHOUSE_REFRIGERATED: 'Warehouse - refrigerated',
|
||||
cte.WAREHOUSE_REFRIGERATED: 'Warehouse',
|
||||
cte.SPORTS_LOCATION: 'Exercise centre',
|
||||
cte.SPORTS_ARENA: 'Sports arena',
|
||||
cte.GYMNASIUM: 'Gymnasium',
|
||||
cte.MOTION_PICTURE_THEATRE: 'Motion picture theatre',
|
||||
cte.MUSEUM: 'Museum',
|
||||
cte.PERFORMING_ARTS_THEATRE: 'Performing arts theatre',
|
||||
cte.TRANSPORTATION: 'Transportation',
|
||||
cte.TRANSPORTATION: 'Transportation facility',
|
||||
cte.AUTOMOTIVE_FACILITY: 'Automotive facility',
|
||||
cte.PARKING_GARAGE: 'Parking garage',
|
||||
cte.RELIGIOUS: 'Religious',
|
||||
cte.PARKING_GARAGE: 'Storage garage',
|
||||
cte.RELIGIOUS: 'Religious building',
|
||||
cte.NON_HEATED: 'n/a'
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ class NrelPhysicsParameters:
|
|||
construction_period_limits = building_archetype.construction_period.split(' - ')
|
||||
if construction_period_limits[1] == 'PRESENT':
|
||||
construction_period_limits[1] = 3000
|
||||
if int(construction_period_limits[0]) <= year_of_construction < int(construction_period_limits[1]):
|
||||
if int(construction_period_limits[0]) <= int(year_of_construction) < int(construction_period_limits[1]):
|
||||
if (str(function) == str(building_archetype.function)) and \
|
||||
(climate_zone == str(building_archetype.climate_zone)):
|
||||
return building_archetype
|
||||
|
|
|
@ -4,7 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guillermo Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
import datetime
|
||||
|
||||
import json
|
||||
|
||||
import numpy as np
|
||||
|
@ -181,7 +181,6 @@ class Geojson:
|
|||
Get city out of a Geojson file
|
||||
"""
|
||||
if self._city is None:
|
||||
start = datetime.datetime.now()
|
||||
missing_functions = []
|
||||
buildings = []
|
||||
building_id = 0
|
||||
|
@ -230,18 +229,12 @@ class Geojson:
|
|||
[polygon])
|
||||
|
||||
self._city = City([self._min_x, self._min_y, 0.0], [self._max_x, self._max_y, self._max_z], 'epsg:26911')
|
||||
print(f'features: {datetime.datetime.now()-start}')
|
||||
|
||||
for building in buildings:
|
||||
self._city.add_city_object(building)
|
||||
self._city.level_of_detail.geometry = lod
|
||||
if lod == 1:
|
||||
start = datetime.datetime.now()
|
||||
lines_information = GeometryHelper.city_mapping(self._city, plot=False)
|
||||
print(f'mapping: {datetime.datetime.now() - start}')
|
||||
start = datetime.datetime.now()
|
||||
self._store_shared_percentage_to_walls(self._city, lines_information)
|
||||
print(f'shared_walls: {datetime.datetime.now() - start}')
|
||||
if len(missing_functions) > 0:
|
||||
print(f'There are unknown functions {missing_functions}')
|
||||
return self._city
|
||||
|
|
|
@ -21,7 +21,7 @@ class InselMonthlyEnergyBalance:
|
|||
self._base_path = base_path
|
||||
|
||||
@staticmethod
|
||||
def _demand(insel_output_file_path):
|
||||
def _conditioning_demand(insel_output_file_path):
|
||||
heating = []
|
||||
cooling = []
|
||||
with open(Path(insel_output_file_path).resolve()) as csv_file:
|
||||
|
@ -40,15 +40,74 @@ class InselMonthlyEnergyBalance:
|
|||
monthly_cooling = pd.DataFrame(cooling, columns=[cte.INSEL_MEB]).astype(float)
|
||||
return monthly_heating, monthly_cooling
|
||||
|
||||
def _dhw_demand(self):
|
||||
for building in self._city.buildings:
|
||||
domestic_hot_water_demand = []
|
||||
if building.internal_zones[0].thermal_zones is None:
|
||||
domestic_hot_water_demand = [0] * 12
|
||||
else:
|
||||
thermal_zone = building.internal_zones[0].thermal_zones[0]
|
||||
area = thermal_zone.total_floor_area
|
||||
cold_water = building.cold_water_temperature[cte.MONTH]['epw']
|
||||
for month in range(0, 12):
|
||||
total_dhw_demand = 0
|
||||
for schedule in thermal_zone.domestic_hot_water.schedules:
|
||||
total_day = 0
|
||||
for value in schedule.values:
|
||||
total_day += value
|
||||
for day_type in schedule.day_types:
|
||||
demand = thermal_zone.domestic_hot_water.peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY \
|
||||
* (thermal_zone.domestic_hot_water.service_temperature - cold_water[month])
|
||||
total_dhw_demand += total_day * cte.DAYS_A_MONTH[day_type][month] * demand
|
||||
domestic_hot_water_demand.append(total_dhw_demand * area)
|
||||
|
||||
building.domestic_hot_water_heat_demand[cte.MONTH] = \
|
||||
pd.DataFrame(domestic_hot_water_demand, columns=[cte.INSEL_MEB])
|
||||
|
||||
def _electrical_demand(self):
|
||||
for building in self._city.buildings:
|
||||
lighting_demand = []
|
||||
appliances_demand = []
|
||||
if building.internal_zones[0].thermal_zones is None:
|
||||
lighting_demand = [0] * 12
|
||||
appliances_demand = [0] * 12
|
||||
else:
|
||||
thermal_zone = building.internal_zones[0].thermal_zones[0]
|
||||
area = thermal_zone.total_floor_area
|
||||
|
||||
for month in range(0, 12):
|
||||
total_lighting = 0
|
||||
for schedule in thermal_zone.lighting.schedules:
|
||||
total_day = 0
|
||||
for value in schedule.values:
|
||||
total_day += value
|
||||
for day_type in schedule.day_types:
|
||||
total_lighting += total_day * cte.DAYS_A_MONTH[day_type][month] * thermal_zone.lighting.density
|
||||
lighting_demand.append(total_lighting * area)
|
||||
|
||||
total_appliances = 0
|
||||
for schedule in thermal_zone.appliances.schedules:
|
||||
total_day = 0
|
||||
for value in schedule.values:
|
||||
total_day += value
|
||||
for day_type in schedule.day_types:
|
||||
total_appliances += total_day * cte.DAYS_A_MONTH[day_type][month] * thermal_zone.appliances.density
|
||||
appliances_demand.append(total_appliances * area)
|
||||
|
||||
building.lighting_electrical_demand[cte.MONTH] = pd.DataFrame(lighting_demand, columns=[cte.INSEL_MEB])
|
||||
building.appliances_electrical_demand[cte.MONTH] = pd.DataFrame(appliances_demand, columns=[cte.INSEL_MEB])
|
||||
|
||||
def enrich(self):
|
||||
for building in self._city.buildings:
|
||||
file_name = building.name + '.out'
|
||||
insel_output_file_path = Path(self._base_path / file_name).resolve()
|
||||
if insel_output_file_path.is_file():
|
||||
building.heating[cte.MONTH], building.cooling[cte.MONTH] = self._demand(insel_output_file_path)
|
||||
building.heating[cte.MONTH], building.cooling[cte.MONTH] = self._conditioning_demand(insel_output_file_path)
|
||||
building.heating[cte.YEAR] = pd.DataFrame(
|
||||
[building.heating[cte.MONTH][cte.INSEL_MEB].astype(float).sum()], columns=[cte.INSEL_MEB]
|
||||
)
|
||||
building.cooling[cte.YEAR] = pd.DataFrame(
|
||||
[building.cooling[cte.MONTH][cte.INSEL_MEB].astype(float).sum()], columns=[cte.INSEL_MEB]
|
||||
)
|
||||
self._dhw_demand()
|
||||
self._electrical_demand()
|
||||
|
|
|
@ -83,7 +83,6 @@ class NrcanUsageParameters:
|
|||
if archetype.mechanical_air_change > 0:
|
||||
usage.mechanical_air_change = archetype.mechanical_air_change
|
||||
elif archetype.ventilation_rate > 0:
|
||||
print(volume_per_area)
|
||||
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area * cte.HOUR_TO_SECONDS
|
||||
else:
|
||||
usage.mechanical_air_change = 0
|
||||
|
|
|
@ -37,7 +37,7 @@ class EpwWeatherParameters:
|
|||
depth_measurement_ground_temperature = line[i*16+2]
|
||||
temperatures = []
|
||||
for j in range(0, 12):
|
||||
temperatures.append(line[i*16+j+6])
|
||||
temperatures.append(float(line[i*16+j+6]))
|
||||
ground_temperature[depth_measurement_ground_temperature] = temperatures
|
||||
file.close()
|
||||
except SystemExit:
|
||||
|
@ -74,6 +74,13 @@ class EpwWeatherParameters:
|
|||
|
||||
for building in self._city.buildings:
|
||||
building.ground_temperature[cte.MONTH] = ground_temperature
|
||||
ground_temperature = {}
|
||||
for set in building.ground_temperature[cte.MONTH]:
|
||||
temperature = 0
|
||||
for value in building.ground_temperature[cte.MONTH][set]:
|
||||
temperature += value / 12
|
||||
ground_temperature[set] = [temperature]
|
||||
building.ground_temperature[cte.YEAR] = ground_temperature
|
||||
if cte.HOUR in building.external_temperature:
|
||||
del building.external_temperature[cte.HOUR]
|
||||
new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw'])
|
||||
|
@ -131,4 +138,26 @@ class EpwWeatherParameters:
|
|||
if cte.YEAR not in building.cold_water_temperature:
|
||||
building.cold_water_temperature[cte.YEAR] = wh().get_yearly_mean_values(
|
||||
building.cold_water_temperature[cte.HOUR][['epw']])
|
||||
|
||||
# If the usage has already being imported, the domestic hot water missing values must be calculated here that
|
||||
# the cold water temperature is finally known
|
||||
cold_temperature = building.cold_water_temperature[cte.YEAR]['epw']
|
||||
for internal_zone in building.internal_zones:
|
||||
if internal_zone.usages is not None:
|
||||
for usage in internal_zone.usages:
|
||||
if usage.domestic_hot_water.peak_flow is None:
|
||||
if usage.domestic_hot_water.density is None:
|
||||
continue
|
||||
peak_flow = 0
|
||||
if (usage.domestic_hot_water.service_temperature - cold_temperature) > 0:
|
||||
peak_flow = usage.domestic_hot_water.density / cte.WATER_DENSITY / cte.WATER_HEAT_CAPACITY \
|
||||
/ (usage.domestic_hot_water.service_temperature - cold_temperature)
|
||||
usage.domestic_hot_water.peak_flow = peak_flow
|
||||
if usage.domestic_hot_water.density is None:
|
||||
if usage.domestic_hot_water.peak_flow is None:
|
||||
continue
|
||||
density = usage.domestic_hot_water.peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY \
|
||||
* (usage.domestic_hot_water.service_temperature - cold_temperature)
|
||||
usage.domestic_hot_water.density = density
|
||||
|
||||
self._city.level_of_detail.weather = 2
|
||||
|
|
|
@ -59,7 +59,6 @@ class CityLayerTest(TestCase):
|
|||
return gdf, target_buildings, adjacent_buildings
|
||||
|
||||
def _genidf(self, bldgs_group):
|
||||
t0 = time.time()
|
||||
buildings_df, target_buildings, adjacent_buildings = self._prepare_buildings(bldgs_group)
|
||||
#output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
city = GeometryFactory('gpandas', data_frame=buildings_df).city
|
||||
|
@ -70,7 +69,6 @@ class CityLayerTest(TestCase):
|
|||
filepath = os.path.join(output_path, city.name + ".idf")
|
||||
newfilepath = filepath[:-4] + "_" + uuid.uuid4().hex[:10] + ".idf"
|
||||
os.rename(filepath, newfilepath)
|
||||
print(f"It took {round((time.time() - t0), 0)} seconds")
|
||||
return newfilepath
|
||||
|
||||
def test_city_layers(self):
|
||||
|
|
|
@ -17,7 +17,7 @@ class TestCostsCatalog(TestCase):
|
|||
catalog_categories = catalog.names()
|
||||
self.assertIsNotNone(catalog, 'catalog is none')
|
||||
content = catalog.entries()
|
||||
self.assertTrue(len(content.archetypes) == 1)
|
||||
self.assertTrue(len(content.archetypes) == 2)
|
||||
|
||||
# retrieving all the entries should not raise any exceptions
|
||||
for category in catalog_categories:
|
||||
|
|
|
@ -4,7 +4,11 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
import unittest
|
||||
from unittest import TestCase
|
||||
|
||||
import sqlalchemy.exc
|
||||
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.db_factory import DBFactory
|
||||
from hub.imports.user_factory import UserFactory
|
||||
|
@ -16,6 +20,40 @@ from hub.persistence.models import User, UserRoles
|
|||
from sqlalchemy.exc import ProgrammingError
|
||||
import uuid
|
||||
|
||||
class Skip:
|
||||
|
||||
_value = False
|
||||
_message = 'PostgreSQL not properly installed in host machine'
|
||||
|
||||
def __init__(self):
|
||||
# Create test database
|
||||
env = '/usr/local/etc/hub/.env'
|
||||
repo = Repository(db_name='test_db', app_env='TEST', dotenv_path=env)
|
||||
eng = create_engine(f'postgresql://{repo.configuration.get_db_user()}@/{repo.configuration.get_db_user()}')
|
||||
try:
|
||||
# delete test database if it exists
|
||||
conn = eng.connect()
|
||||
conn.execute('commit')
|
||||
conn.execute('DROP DATABASE test_db')
|
||||
conn.close()
|
||||
except ProgrammingError as err:
|
||||
print(f'Database does not exist. Nothing to delete')
|
||||
except sqlalchemy.exc.OperationalError:
|
||||
self._value = True
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self._value
|
||||
|
||||
@property
|
||||
def message(self):
|
||||
return self._message
|
||||
|
||||
@value.setter
|
||||
def value(self, skip_value):
|
||||
self._value = skip_value
|
||||
|
||||
skip = Skip()
|
||||
|
||||
class TestDBFactory(TestCase):
|
||||
"""
|
||||
|
@ -32,7 +70,6 @@ class TestDBFactory(TestCase):
|
|||
env = '/usr/local/etc/hub/.env'
|
||||
repo = Repository(db_name='test_db', app_env='TEST', dotenv_path=env)
|
||||
eng = create_engine(f'postgresql://{repo.configuration.get_db_user()}@/{repo.configuration.get_db_user()}')
|
||||
|
||||
try:
|
||||
# delete test database if it exists
|
||||
conn = eng.connect()
|
||||
|
@ -41,7 +78,9 @@ class TestDBFactory(TestCase):
|
|||
conn.close()
|
||||
except ProgrammingError as err:
|
||||
print(f'Database does not exist. Nothing to delete')
|
||||
|
||||
except sqlalchemy.exc.OperationalError:
|
||||
skip.value = True
|
||||
return
|
||||
cnn = eng.connect()
|
||||
cnn.execute('commit')
|
||||
cnn.execute("CREATE DATABASE test_db")
|
||||
|
@ -62,11 +101,13 @@ class TestDBFactory(TestCase):
|
|||
cls._user = user_factory.create_user("Admin", cls.application.id, "Admin@123", UserRoles.Admin)
|
||||
cls.pickle_path = 'tests_data/pickle_path.bz2'
|
||||
|
||||
@unittest.skipIf(skip.value, skip.message)
|
||||
def test_save_application(self):
|
||||
self.assertEqual(self.application.name, "test")
|
||||
self.assertEqual(self.application.description, "test application")
|
||||
self.assertEqual(str(self.application.application_uuid), self.unique_id)
|
||||
|
||||
@unittest.skipIf(skip.value, skip.message)
|
||||
def test_save_city(self):
|
||||
self.city.name = "Montréal"
|
||||
saved_city = self._db_factory.persist_city(self.city, self.pickle_path, self.application.id, self._user.id)
|
||||
|
@ -75,6 +116,7 @@ class TestDBFactory(TestCase):
|
|||
self.assertEqual(saved_city.level_of_detail, self.city.level_of_detail.geometry)
|
||||
self._db_factory.delete_city(saved_city.id)
|
||||
|
||||
@unittest.skipIf(skip.value, skip.message)
|
||||
def test_get_city_by_name(self):
|
||||
city = self._db_factory.persist_city(self.city, self.pickle_path, self.application.id, self._user.id)
|
||||
retrieved_city = self._export_db_factory.get_city_by_name(city.name)
|
||||
|
@ -82,18 +124,21 @@ class TestDBFactory(TestCase):
|
|||
self.assertEqual(retrieved_city[0].user_id, self._user.id)
|
||||
self._db_factory.delete_city(city.id)
|
||||
|
||||
@unittest.skipIf(skip.value, skip.message)
|
||||
def test_get_city_by_user(self):
|
||||
city = self._db_factory.persist_city(self.city, self.pickle_path, self.application.id, self._user.id)
|
||||
retrieved_city = self._export_db_factory.get_city_by_user(self._user.id)
|
||||
self.assertEqual(retrieved_city[0].pickle_path, self.pickle_path)
|
||||
self._db_factory.delete_city(city.id)
|
||||
|
||||
@unittest.skipIf(skip.value, skip.message)
|
||||
def test_get_city_by_id(self):
|
||||
city = self._db_factory.persist_city(self.city, self.pickle_path, self.application.id, self._user.id)
|
||||
retrieved_city = self._export_db_factory.get_city(city.id)
|
||||
self.assertEqual(retrieved_city.level_of_detail, self.city.level_of_detail.geometry)
|
||||
self._db_factory.delete_city(city.id)
|
||||
|
||||
@unittest.skipIf(skip.value, skip.message)
|
||||
def test_get_update_city(self):
|
||||
city = self._db_factory.persist_city(self.city, self.pickle_path, self.application.id, self._user.id)
|
||||
self.city.name = "Ottawa"
|
||||
|
|
|
@ -106,13 +106,12 @@ class TestExports(TestCase):
|
|||
path=file_path,
|
||||
function_to_hub=Dictionaries().alkis_function_to_hub_function).city
|
||||
self.assertIsNotNone(city, 'city is none')
|
||||
ConstructionFactory('nrcan', city=city)
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
# EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
# ConstructionFactory('nrcan', city).enrich()
|
||||
# EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
try:
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export_debug()
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path,
|
||||
target_buildings=['gml_1066158', 'gml_1066159']).export()
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
except Exception:
|
||||
self.fail("Idf ExportsFactory raised ExceptionType unexpectedly!")
|
||||
|
||||
|
|
|
@ -51,8 +51,9 @@ class TestUsageFactory(TestCase):
|
|||
self.assertIsNotNone(building.walls, 'building walls is none')
|
||||
self.assertIsNotNone(building.roofs, 'building roofs is none')
|
||||
for internal_zone in building.internal_zones:
|
||||
self.assertTrue(len(internal_zone.usages) > 0, 'usage zones are not defined')
|
||||
self.assertIsNone(internal_zone.thermal_zones, 'thermal zones are defined')
|
||||
if internal_zone.usages is not None:
|
||||
self.assertTrue(len(internal_zone.usages) > 0, 'usage zones are not defined')
|
||||
self.assertIsNone(internal_zone.thermal_zones, 'thermal zones are defined')
|
||||
self.assertIsNone(building.basement_heated, 'building basement_heated is not none')
|
||||
self.assertIsNone(building.attic_heated, 'building attic_heated is not none')
|
||||
self.assertIsNone(building.terrains, 'building terrains is not none')
|
||||
|
@ -66,7 +67,6 @@ class TestUsageFactory(TestCase):
|
|||
self.assertIsNotNone(building.roof_type, 'building roof type is none')
|
||||
self.assertIsNotNone(building.floor_area, 'building floor_area is none')
|
||||
self.assertIsNone(building.households, 'building households is not none')
|
||||
self.assertTrue(building.is_conditioned, 'building is not conditioned')
|
||||
|
||||
def _check_usage(self, usage):
|
||||
self.assertIsNotNone(usage.name, 'usage is none')
|
||||
|
@ -128,3 +128,59 @@ class TestUsageFactory(TestCase):
|
|||
self.assertIsNotNone(usage.domestic_hot_water.service_temperature,
|
||||
'domestic hot water service temperature is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.schedules, 'domestic hot water schedules is none')
|
||||
|
||||
def test_import_nrcan(self):
|
||||
"""
|
||||
Enrich the city with the usage information from nrcan and verify it
|
||||
"""
|
||||
file = 'selected_building.geojson'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='building_height',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
self._check_buildings(city)
|
||||
for building in city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
if internal_zone.usages is not None:
|
||||
self.assertIsNot(len(internal_zone.usages), 0, 'no building usage defined')
|
||||
for usage in internal_zone.usages:
|
||||
self._check_usage(usage)
|
||||
self.assertIsNotNone(usage.mechanical_air_change, 'mechanical air change is none')
|
||||
self.assertIsNotNone(usage.thermal_control.heating_set_point_schedules,
|
||||
'control heating set point schedule is none')
|
||||
self.assertIsNotNone(usage.thermal_control.cooling_set_point_schedules,
|
||||
'control cooling set point schedule is none')
|
||||
self.assertIsNotNone(usage.occupancy, 'occupancy is none')
|
||||
occupancy = usage.occupancy
|
||||
self.assertIsNotNone(occupancy.occupancy_density, 'occupancy density is none')
|
||||
self.assertIsNotNone(occupancy.latent_internal_gain, 'occupancy latent internal gain is none')
|
||||
self.assertIsNotNone(occupancy.sensible_convective_internal_gain,
|
||||
'occupancy sensible convective internal gain is none')
|
||||
self.assertIsNotNone(occupancy.sensible_radiative_internal_gain,
|
||||
'occupancy sensible radiant internal gain is none')
|
||||
self.assertIsNotNone(occupancy.occupancy_schedules, 'occupancy schedule is none')
|
||||
self.assertIsNotNone(usage.lighting, 'lighting is none')
|
||||
lighting = usage.lighting
|
||||
self.assertIsNotNone(lighting.density, 'lighting density is none')
|
||||
self.assertIsNotNone(lighting.latent_fraction, 'lighting latent fraction is none')
|
||||
self.assertIsNotNone(lighting.convective_fraction, 'lighting convective fraction is none')
|
||||
self.assertIsNotNone(lighting.radiative_fraction, 'lighting radiant fraction is none')
|
||||
self.assertIsNotNone(lighting.schedules, 'lighting schedule is none')
|
||||
self.assertIsNotNone(usage.appliances, 'appliances is none')
|
||||
appliances = usage.appliances
|
||||
self.assertIsNotNone(appliances.density, 'appliances density is none')
|
||||
self.assertIsNotNone(appliances.latent_fraction, 'appliances latent fraction is none')
|
||||
self.assertIsNotNone(appliances.convective_fraction, 'appliances convective fraction is none')
|
||||
self.assertIsNotNone(appliances.radiative_fraction, 'appliances radiant fraction is none')
|
||||
self.assertIsNotNone(appliances.schedules, 'appliances schedule is none')
|
||||
self.assertIsNotNone(usage.thermal_control.hvac_availability_schedules,
|
||||
'control hvac availability is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.peak_flow, 'domestic hot water peak flow is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.service_temperature,
|
||||
'domestic hot water service temperature is none')
|
||||
self.assertIsNotNone(usage.domestic_hot_water.schedules, 'domestic hot water schedules is none')
|
||||
|
|
|
@ -23,4 +23,4 @@ shapely
|
|||
geopandas
|
||||
triangle
|
||||
psycopg2-binary
|
||||
PIL
|
||||
Pillow
|
5
setup.py
5
setup.py
|
@ -5,13 +5,12 @@ from distutils.util import convert_path
|
|||
import pkg_resources
|
||||
from setuptools import setup
|
||||
|
||||
with pathlib.Path('hub/requirements.txt').open() as r:
|
||||
with pathlib.Path('requirements.txt').open() as r:
|
||||
install_requires = [
|
||||
str(requirement)
|
||||
for requirement
|
||||
in pkg_resources.parse_requirements(r)
|
||||
]
|
||||
|
||||
install_requires.append('setuptools')
|
||||
|
||||
main_ns = {}
|
||||
|
@ -82,7 +81,7 @@ setup(
|
|||
],
|
||||
setup_requires=install_requires,
|
||||
data_files=[
|
||||
('hub', glob.glob('hub/requirements.txt')),
|
||||
('hub', glob.glob('requirements.txt')),
|
||||
('hub/config', glob.glob('hub/config/*.ini')),
|
||||
('hub/catalog_factories/greenery/ecore_greenery', glob.glob('hub/catalog_factories/greenery/ecore_greenery/*.ecore')),
|
||||
('hub/data/construction.', glob.glob('hub/data/construction/*')),
|
||||
|
|
Loading…
Reference in New Issue
Block a user