forked from s_ranjbar/city_retrofit
Merge remote-tracking branch 'origin/geojson'
This commit is contained in:
commit
604e6d5eb2
|
@ -20,7 +20,7 @@ from hub.catalog_factories.data_models.cost.cost_helper import CostHelper
|
|||
|
||||
class MontrealCustomCatalog(Catalog):
|
||||
def __init__(self, path):
|
||||
path = str(path / 'montreal_costs.xml')
|
||||
path = (path / 'montreal_costs.xml')
|
||||
with open(path) as xml:
|
||||
self._archetypes = xmltodict.parse(xml.read(), force_list='archetype')
|
||||
|
||||
|
@ -67,7 +67,6 @@ class MontrealCustomCatalog(Catalog):
|
|||
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'
|
||||
services = entry['D_services']
|
||||
|
@ -82,7 +81,6 @@ class MontrealCustomCatalog(Catalog):
|
|||
item_description = self._item_with_threesome(services['D50_electrical'], item_type)
|
||||
items_list.append(item_description)
|
||||
general_chapters.append(Chapter('D_services', items_list))
|
||||
|
||||
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
|
||||
|
@ -127,9 +125,9 @@ class MontrealCustomCatalog(Catalog):
|
|||
for archetype in archetypes:
|
||||
function = archetype['@function']
|
||||
municipality = archetype['@municipality']
|
||||
country = archetype['@country']
|
||||
lod = float(archetype['@lod'])
|
||||
currency = archetype['currency']
|
||||
country = 'CA'#archetype['@country']
|
||||
lod = 0 #float(archetype['@lod'])
|
||||
currency = 'CAD'#archetype['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'])
|
||||
|
|
|
@ -38,7 +38,7 @@ class Archetype:
|
|||
Get name
|
||||
:return: string
|
||||
"""
|
||||
return f'{self._country}_{self._municipality}_{self._function}_{self._lod}'
|
||||
return f'{self._country}_{self._municipality}_{self._function}_lod{self._lod}'
|
||||
|
||||
@property
|
||||
def lod(self):
|
||||
|
|
|
@ -38,3 +38,13 @@ class CapitalCost:
|
|||
:return: float
|
||||
"""
|
||||
return self._overhead_and_profit
|
||||
|
||||
def chapter(self, name) -> Chapter:
|
||||
"""
|
||||
Get specific chapter by name
|
||||
:return: Chapter
|
||||
"""
|
||||
for chapter in self.general_chapters:
|
||||
if chapter.chapter_type == name:
|
||||
return chapter
|
||||
raise KeyError(f'Chapter name {name} not found')
|
||||
|
|
|
@ -30,3 +30,13 @@ class Chapter:
|
|||
:return: [str]
|
||||
"""
|
||||
return self._items
|
||||
|
||||
def item(self, name) -> ItemDescription:
|
||||
"""
|
||||
Get specific item by name
|
||||
:return: ItemDescription
|
||||
"""
|
||||
for item in self.items:
|
||||
if item.type == name:
|
||||
return item
|
||||
raise KeyError(f'Item name {name} not found')
|
||||
|
|
|
@ -18,6 +18,8 @@ class ThermalControl:
|
|||
hvac_availability_schedules,
|
||||
heating_set_point_schedules,
|
||||
cooling_set_point_schedules):
|
||||
#todo: eliminate negative value
|
||||
deltaTsetpoint=0
|
||||
self._mean_heating_set_point = mean_heating_set_point
|
||||
self._heating_set_back = heating_set_back
|
||||
self._mean_cooling_set_point = mean_cooling_set_point
|
||||
|
|
|
@ -49,7 +49,8 @@ class NrcanCatalog(Catalog):
|
|||
hvac_schedule_name = space_type['exhaust_schedule']
|
||||
if 'FAN' in hvac_schedule_name:
|
||||
hvac_schedule_name = hvac_schedule_name.replace('FAN', 'Fan')
|
||||
heating_setpoint_schedule_name = space_type['heating_setpoint_schedule']
|
||||
#todo: get -1 out of the setpoint
|
||||
heating_setpoint_schedule_name = space_type['heating_setpoint_schedule']-1
|
||||
cooling_setpoint_schedule_name = space_type['cooling_setpoint_schedule']
|
||||
occupancy_schedule = self._get_schedules(occupancy_schedule_name)
|
||||
lighting_schedule = self._get_schedules(lighting_schedule_name)
|
||||
|
|
|
@ -131,10 +131,9 @@ class NrcanCatalog(Catalog):
|
|||
mechanical_air_change = space_type['ventilation_air_changes']
|
||||
# cfm/ft2 to m3/m2.s
|
||||
ventilation_rate = space_type['ventilation_per_area'] / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
|
||||
if ventilation_rate == 0:
|
||||
# cfm/person to m3/m2.s
|
||||
ventilation_rate = space_type['ventilation_per_person'] / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)\
|
||||
/ occupancy_density
|
||||
# cfm/person to m3/m2.s
|
||||
ventilation_rate += space_type['ventilation_per_person'] / (pow(cte.METERS_TO_FEET, 3) * cte.MINUTES_TO_SECONDS)\
|
||||
* occupancy_density
|
||||
|
||||
lighting_radiative_fraction = space_type['lighting_fraction_radiant']
|
||||
lighting_convective_fraction = 0
|
||||
|
|
|
@ -9,8 +9,11 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
|
|||
import sys
|
||||
from typing import List, Union
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from hub.hub_logger import logger
|
||||
import hub.helpers.constants as cte
|
||||
import hub.helpers.peak_loads as pl
|
||||
from hub.city_model_structure.building_demand.surface import Surface
|
||||
from hub.city_model_structure.city_object import CityObject
|
||||
from hub.city_model_structure.building_demand.household import Household
|
||||
|
@ -362,6 +365,36 @@ class Building(CityObject):
|
|||
"""
|
||||
self._domestic_hot_water_heat_demand = value
|
||||
|
||||
@property
|
||||
def heating_peak_load(self) -> dict:
|
||||
"""
|
||||
Get heating peak load in W
|
||||
:return: dict{DataFrame(float)}
|
||||
"""
|
||||
results = {}
|
||||
if cte.HOUR in self.heating:
|
||||
monthly_values = pl.peak_loads_from_hourly(self.heating[cte.HOUR][next(iter(self.heating[cte.HOUR]))].values)
|
||||
else:
|
||||
monthly_values = pl.heating_peak_loads_from_methodology(self)
|
||||
results[cte.MONTH] = pd.DataFrame(monthly_values, columns=['heating peak loads'])
|
||||
results[cte.YEAR] = pd.DataFrame([max(monthly_values)], columns=['heating peak loads'])
|
||||
return results
|
||||
|
||||
@property
|
||||
def cooling_peak_load(self) -> dict:
|
||||
"""
|
||||
Get cooling peak load in W
|
||||
:return: dict{DataFrame(float)}
|
||||
"""
|
||||
results = {}
|
||||
if cte.HOUR in self.cooling:
|
||||
monthly_values = pl.peak_loads_from_hourly(self.cooling[cte.HOUR][next(iter(self.cooling[cte.HOUR]))])
|
||||
else:
|
||||
monthly_values = pl.cooling_peak_loads_from_methodology(self)
|
||||
results[cte.MONTH] = pd.DataFrame(monthly_values, columns=['cooling peak loads'])
|
||||
results[cte.YEAR] = pd.DataFrame([max(monthly_values)], columns=['cooling peak loads'])
|
||||
return results
|
||||
|
||||
@property
|
||||
def eave_height(self):
|
||||
"""
|
||||
|
|
|
@ -78,7 +78,7 @@ class InternalZone:
|
|||
def usages(self) -> [Usage]:
|
||||
"""
|
||||
Get internal zone usage zones
|
||||
:return: [UsageZone]
|
||||
:return: [Usage]
|
||||
"""
|
||||
return self._usages
|
||||
|
||||
|
@ -86,7 +86,7 @@ class InternalZone:
|
|||
def usages(self, value):
|
||||
"""
|
||||
Set internal zone usage zones
|
||||
:param value: [UsageZone]
|
||||
:param value: [Usage]
|
||||
"""
|
||||
self._usages = value
|
||||
|
||||
|
|
|
@ -630,6 +630,7 @@ class ThermalZone:
|
|||
schedule.values = new_values
|
||||
_schedules.append(schedule)
|
||||
self._domestic_hot_water.schedules = _schedules
|
||||
|
||||
return self._domestic_hot_water
|
||||
|
||||
@property
|
||||
|
|
|
@ -122,6 +122,8 @@ class City:
|
|||
Get the name for the climatic information reference city
|
||||
:return: None or str
|
||||
"""
|
||||
if self._climate_reference_city is None:
|
||||
self._climate_reference_city = self._get_location().city
|
||||
return self._climate_reference_city
|
||||
|
||||
@climate_reference_city.setter
|
||||
|
@ -130,8 +132,7 @@ class City:
|
|||
Set the name for the climatic information reference city
|
||||
:param value: str
|
||||
"""
|
||||
if value is not None:
|
||||
self._climate_reference_city = str(value)
|
||||
self._climate_reference_city = str(value)
|
||||
|
||||
@property
|
||||
def climate_file(self) -> Union[None, Path]:
|
||||
|
|
|
@ -110,6 +110,14 @@ class CityObject:
|
|||
"""
|
||||
return self._surfaces
|
||||
|
||||
@surfaces.setter
|
||||
def surfaces(self, value):
|
||||
"""
|
||||
Set city object surfaces
|
||||
:return: [Surface]
|
||||
"""
|
||||
self._surfaces = value
|
||||
|
||||
def surface(self, name) -> Union[Surface, None]:
|
||||
"""
|
||||
Get the city object surface with a given name
|
||||
|
|
File diff suppressed because it is too large
Load Diff
166
hub/data/costs/montreal_costs_oriol.xml
Normal file
166
hub/data/costs/montreal_costs_oriol.xml
Normal file
|
@ -0,0 +1,166 @@
|
|||
<archetypes>
|
||||
<archetype function="residential" municipality="montreal" currency="CAD">
|
||||
<capital_cost>
|
||||
<ASubstructure>
|
||||
<A10sub_structural cost_unit="currency/m2"> 15.89 </A10sub_structural>
|
||||
<A20structural cost_unit="currency/m3"> 215.90 </A20structural>
|
||||
</ASubstructure>
|
||||
<BShell>
|
||||
<B10superstructure>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</B10superstructure>
|
||||
<B20envelope>
|
||||
<B2010opaquewalls>
|
||||
<reposition cost_unit="currency/m2"> 304 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 304 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</B2010opaquewalls>
|
||||
<B2020transparent>
|
||||
<reposition cost_unit="currency/m2"> 857.14 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 857.14 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</B2020transparent>
|
||||
</B20envelope>
|
||||
<B30roofing>
|
||||
<B3010opaqueroof>
|
||||
<reposition cost_unit="currency/m2"> 118 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 118 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</B3010opaqueroof>
|
||||
<B3020transparentroof>
|
||||
<reposition cost_unit="currency/m2"> 857.14 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 857.14 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</B3020transparentroof>
|
||||
</B30roofing>
|
||||
</BShell>
|
||||
<CInteriors>
|
||||
<C10Interiorconstruction>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</C10Interiorconstruction>
|
||||
<C20Stairs>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</C20Stairs>
|
||||
<C30Interiorfinishes>
|
||||
<C3010Walls>
|
||||
<reposition cost_unit="currency/m2"> 50 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 50 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</C3010Walls>
|
||||
<C3020Floors>
|
||||
<reposition cost_unit="currency/m2"> 62 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 62 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</C3020Floors>
|
||||
<C3030Ceilings>
|
||||
<reposition cost_unit="currency/m2"> 70 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 70 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</C3030Ceilings>
|
||||
</C30Interiorfinishes>
|
||||
</CInteriors>
|
||||
<DServices>
|
||||
<D10Conveying cost_unit="currency/m2"> 0 </D10Conveying>
|
||||
<D20Plumbing cost_unit="currency/m2"> 100 </D20Plumbing>
|
||||
<D30HVAC>
|
||||
<D3010EnergySupply>
|
||||
<D301010photovoltaic_system>
|
||||
<initial_investment cost_unit="currency/m2"> 800 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 800 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D301010photovoltaic_system>
|
||||
</D3010EnergySupply>
|
||||
<D3020Heatgeneratingsystems>
|
||||
<initial_investment cost_unit="currency/kW"> 622.86 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 622.86 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D3020Heatgeneratingsystems>
|
||||
<D3030Coolinggenerationsystems>
|
||||
<initial_investment cost_unit="currency/kW"> 622.86 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 622.86 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3030Coolinggenerationsystems>
|
||||
<D3040Distributionsystems>
|
||||
<initial_investment cost_unit="currency/kW"> 0 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3040Distributionsystems>
|
||||
<D3060Controlsandinstrumentation>
|
||||
<initial_investment cost_unit="currency/kW"> 0 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3060Controlsandinstrumentation>
|
||||
<D3080OtherHVAC_AHU>
|
||||
<initial_investment cost_unit="currency/kW"> 47.62 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 47.62 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3080OtherHVAC_AHU>
|
||||
</D30HVAC>
|
||||
<D50Electrical>
|
||||
<D5010Electricalservicesanddistribution>
|
||||
<initial_investment cost_unit="currency/m2"> 171.43 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 171.43 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</D5010Electricalservicesanddistribution>
|
||||
<D5020Lightingandbranchwiring>
|
||||
<initial_investment cost_unit="currency/kW"> 139 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 139 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</D5020Lightingandbranchwiring>
|
||||
</D50Electrical>
|
||||
</DServices>
|
||||
<EEquimentsandfurnishing>
|
||||
<E10Equipments>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</E10Equipments>
|
||||
<E10Furnishing>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</E10Furnishing>
|
||||
</EEquimentsandfurnishing>
|
||||
<engineer cost_unit="%"> 2.5 </engineer>
|
||||
</capital_cost>
|
||||
<operational_cost>
|
||||
<fuel fuel_type="electricity">
|
||||
<fixed>
|
||||
<fixed_monthly cost_unit="currency/month"> 0 </fixed_monthly>
|
||||
<fixed_power cost_unit="currency/kW"> 0 </fixed_power>
|
||||
</fixed>
|
||||
<variable cost_unit="currency/kWh"> 5.6 </variable>
|
||||
</fuel>
|
||||
<maintenance>
|
||||
<heating_equipment cost_unit="currency/kW"> 40 </heating_equipment>
|
||||
<cooling_equipment cost_unit="currency/kW"> 40 </cooling_equipment>
|
||||
<general_hvac_equipment cost_unit="currency/(m3/h)"> 0.05 </general_hvac_equipment>
|
||||
<photovoltaic_system cost_unit="currency/m2"> 1 </photovoltaic_system>
|
||||
<other_systems cost_unit="currency/m2"> 4.6 </other_systems>
|
||||
</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>
|
||||
<construction_subsidy cost_unit="%"> 2 </construction_subsidy>
|
||||
<hvac_subsidy cost_unit="%"> 1.5 </hvac_subsidy>
|
||||
<photovoltaic_subsidy cost_unit="%"> 3.6 </photovoltaic_subsidy>
|
||||
</subsidies>
|
||||
<energy_exports>
|
||||
<electricity cost_unit="currency/kWh"> hourlydatatable </electricity>
|
||||
<heat cost_unit="currency/kWh"> 0 </heat>
|
||||
</energy_exports>
|
||||
<tax_reductions>
|
||||
<reductions_taxes cost_unit="%"> 2 </reductions_taxes>
|
||||
</tax_reductions>
|
||||
<CO2_income cost_unit="currency/kgCO2exported"> 0 </CO2_income>
|
||||
</incomes>
|
||||
</archetype>
|
||||
</archetypes>
|
212
hub/data/costs/montreal_costs_oriol_LOD0.xml
Normal file
212
hub/data/costs/montreal_costs_oriol_LOD0.xml
Normal file
|
@ -0,0 +1,212 @@
|
|||
<archetypes>
|
||||
<archetype function="residential" municipality="montreal" currency="CAD">
|
||||
<capital_cost>
|
||||
<B_Shell>
|
||||
<B10_superstructure>
|
||||
<refurbishment_cost_basement cost_unit="currency/m2"> 0 </refurbishment_cost_basement>
|
||||
</B10_superstructure>
|
||||
<B20_envelope>
|
||||
<B2010_opaquewalls>
|
||||
<refurbishment_cost cost_unit="currency/m2"> 304 </refurbishment_cost>
|
||||
</B2010_opaquewalls>
|
||||
<B2020_transparent>
|
||||
<refurbishment_cost cost_unit="currency/m2"> 857.14 </refurbishment_cost>
|
||||
</B2020_transparent>
|
||||
</B20_envelope>
|
||||
<B30_roofing>
|
||||
<B3010_opaqueroof>
|
||||
<refurbishment_cost cost_unit="currency/m2"> 118 </refurbishment_cost>
|
||||
</B3010_opaqueroof>
|
||||
</B30_roofing>
|
||||
</B_Shell>
|
||||
<D_Services>
|
||||
<D30_HVAC>
|
||||
<D3010_EnergySupply>
|
||||
<D301010_Photovoltaic_system>
|
||||
<initial_investment cost_unit="currency/m2"> 800 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 800 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D301010_Photovoltaic_system>
|
||||
</D3010_EnergySupply>
|
||||
<D3020_Heat_generating_systems>
|
||||
<investment_cost cost_unit="currency/kW"> 622.86 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 622.86 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D3020_Heat_generating_systems>
|
||||
<D3030_Cooling_generation_systems>
|
||||
<investment_cost cost_unit="currency/kW"> 622.86 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 622.86 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3030_Cooling_generation_systems>
|
||||
<D3040_Distributionsystems>
|
||||
<investment_cost cost_unit="currency/kW"> 0 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3040_Distributionsystems>
|
||||
<D3080_OtherHVAC_AHU>
|
||||
<investment_cost cost_unit="currency/kW"> 47.62 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 47.62 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3080_OtherHVAC_AHU>
|
||||
</D30_HVAC>
|
||||
<D50_Electrical>
|
||||
<D5020Lightingandbranchwiring>
|
||||
<refurbishmentcost cost_unit="currency/kW"> 139 </refurbishmentcost>
|
||||
<reposition cost_unit="currency/kW"> 139 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</D5020Lightingandbranchwiring>
|
||||
</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>
|
||||
</Z_Allowances_overhead_profit>
|
||||
</capital_cost>
|
||||
<operational_cost>
|
||||
<fuel fuel_type="electricity">
|
||||
<fixed>
|
||||
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
|
||||
<fixed_power cost_unit="currency/month*kW"> 0 </fixed_power>
|
||||
</fixed>
|
||||
<variable cost_unit="currency/kWh"> 0.075 </variable>
|
||||
</fuel>
|
||||
<fuel fuel_type="gas">
|
||||
<fixed>
|
||||
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
|
||||
</fixed>
|
||||
<variable cost_unit="currency/kWh"> 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>
|
||||
<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>
|
||||
<construction_subsidy cost_unit="%"> 2 </construction_subsidy>
|
||||
<hvac_subsidy cost_unit="%"> 1.5 </hvac_subsidy>
|
||||
<photovoltaic_subsidy cost_unit="%"> 3.6 </photovoltaic_subsidy>
|
||||
</subsidies>
|
||||
<energy_exports>
|
||||
<electricity cost_unit="currency/kWh"> 0 </electricity>
|
||||
</energy_exports>
|
||||
<tax_reductions>
|
||||
<reductions_taxes cost_unit="%"> 2 </reductions_taxes>
|
||||
</tax_reductions>
|
||||
</incomes>
|
||||
</archetype>
|
||||
<archetype function="non-residential" municipality="montreal" currency="CAD">
|
||||
<capital_cost>
|
||||
<B_Shell>
|
||||
<B10_superstructure>
|
||||
<refurbishmentcostbasement cost_unit="currency/m2"> 0 </refurbishmentcostbasement>
|
||||
</B10_superstructure>
|
||||
<B20_envelope>
|
||||
<B2010_opaque_walls>
|
||||
<refurbishmentcost cost_unit="currency/m2"> 304 </refurbishmentcost>
|
||||
</B2010_opaque_walls>
|
||||
<B2020_transparent>
|
||||
<refurbishmentcost cost_unit="currency/m2"> 857.14 </refurbishmentcost>
|
||||
</B2020_transparent>
|
||||
</B20_envelope>
|
||||
<B30_roofing>
|
||||
<B3010_opaqueroof>
|
||||
<refurbishmentcost cost_unit="currency/m2"> 118 </refurbishmentcost>
|
||||
</B3010_opaqueroof>
|
||||
</B30_roofing>
|
||||
</B_Shell>
|
||||
<D_Services>
|
||||
<D30_HVAC>
|
||||
<D3010EnergySupply>
|
||||
<D301010photovoltaic_system>
|
||||
<initial_investment cost_unit="currency/m2"> 800 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 800 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D301010photovoltaic_system>
|
||||
</D3010EnergySupply>
|
||||
<D3020Heatgeneratingsystems>
|
||||
<investment_cost cost_unit="currency/kW"> 622.86 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 622.86 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D3020Heatgeneratingsystems>
|
||||
<D3030_Cooling_generation_systems>
|
||||
<investment_cost cost_unit="currency/kW"> 622.86 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 622.86 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3030_Cooling_generation_systems>
|
||||
<D3040_Distribution_systems>
|
||||
<refurbishmentcost cost_unit="currency/m2"> 0 </refurbishmentcost>
|
||||
<reposition cost_unit="currency/kW"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3040_Distribution_systems>
|
||||
<D3080_Other_HVAC_AHU>
|
||||
<investment_cost cost_unit="currency/kW"> 47.62 </investment_cost>
|
||||
<reposition cost_unit="currency/kW"> 47.62 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3080_Other_HVAC_AHU>
|
||||
</D30_HVAC>
|
||||
<D50_Electrical>
|
||||
<D5020_Lighting_and_branch_wiring>
|
||||
<refurbishmentcost cost_unit="currency/kW"> 139 </refurbishmentcost>
|
||||
<reposition cost_unit="currency/kW"> 139 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</D5020_Lighting_and_branch_wiring>
|
||||
</D50_Electrical>
|
||||
</D_Services>
|
||||
<Z_Allowances_overhead_profit>
|
||||
<Z10_Design_allowance cost_unit="%"> 6 </Z10_Design_allowance>
|
||||
<Z20_Overhead_profit cost_unit="%"> 14 </Z20_Overhead_profit>
|
||||
</Z_Allowances_overhead_profit>
|
||||
</capital_cost>
|
||||
<operational_cost>
|
||||
<fuel fuel_type="electricity">
|
||||
<fixed>
|
||||
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
|
||||
<fixed_power cost_unit="currency/(month*kW)"> 0 </fixed_power>
|
||||
</fixed>
|
||||
<variable cost_unit="currency/kWh"> 0.075 </variable>
|
||||
</fuel>
|
||||
<fuel fuel_type="gas">
|
||||
<fixed>
|
||||
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
|
||||
</fixed>
|
||||
<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>
|
||||
<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>
|
||||
<construction_subsidy cost_unit="%"> 2 </construction_subsidy>
|
||||
<hvac_subsidy cost_unit="%"> 1.5 </hvac_subsidy>
|
||||
<photovoltaic_subsidy cost_unit="%"> 3.6 </photovoltaic_subsidy>
|
||||
</subsidies>
|
||||
<energy_exports>
|
||||
<electricity cost_unit="currency/kWh"> 0 </electricity>
|
||||
</energy_exports>
|
||||
<tax_reductions>
|
||||
<reductions_taxes cost_unit="%"> 2 </reductions_taxes>
|
||||
</tax_reductions>
|
||||
</incomes>
|
||||
</archetype>
|
||||
</archetypes>
|
178
hub/data/costs/montreal_costs_oriol_LOD1.xml
Normal file
178
hub/data/costs/montreal_costs_oriol_LOD1.xml
Normal file
|
@ -0,0 +1,178 @@
|
|||
<archetypes>
|
||||
<archetype function="residential" municipality="montreal" currency="CAD">
|
||||
<capital_cost>
|
||||
<ASubstructure>
|
||||
<A10sub_structural cost_unit="currency/m2"> 15.89 </A10sub_structural>
|
||||
<A20structural cost_unit="currency/m3"> 215.90 </A20structural>
|
||||
</ASubstructure>
|
||||
<BShell>
|
||||
<B10superstructure>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</B10superstructure>
|
||||
<B20envelope>
|
||||
<B2010opaquewalls>
|
||||
<reposition cost_unit="currency/m2"> 304 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 304 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</B2010opaquewalls>
|
||||
<B2020transparent>
|
||||
<reposition cost_unit="currency/m2"> 857.14 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 857.14 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</B2020transparent>
|
||||
</B20envelope>
|
||||
<B30roofing>
|
||||
<B3010opaqueroof>
|
||||
<reposition cost_unit="currency/m2"> 118 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 118 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</B3010opaqueroof>
|
||||
<B3020transparentroof>
|
||||
<reposition cost_unit="currency/m2"> 857.14 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 857.14 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</B3020transparentroof>
|
||||
</B30roofing>
|
||||
</BShell>
|
||||
<CInteriors>
|
||||
<C10Interiorconstruction>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</C10Interiorconstruction>
|
||||
<C20Stairs>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
|
||||
</C20Stairs>
|
||||
<C30Interiorfinishes>
|
||||
<C3010Walls>
|
||||
<reposition cost_unit="currency/m2"> 50 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 50 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</C3010Walls>
|
||||
<C3020Floors>
|
||||
<reposition cost_unit="currency/m2"> 62 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 62 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</C3020Floors>
|
||||
<C3030Ceilings>
|
||||
<reposition cost_unit="currency/m2"> 70 </reposition>
|
||||
<initial_investment cost_unit="currency/m2"> 70 </initial_investment>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</C3030Ceilings>
|
||||
</C30Interiorfinishes>
|
||||
</CInteriors>
|
||||
<DServices>
|
||||
<D10Conveying cost_unit="currency/m2"> 0 </D10Conveying>
|
||||
<D20Plumbing cost_unit="currency/m2"> 100 </D20Plumbing>
|
||||
<D30HVAC>
|
||||
<D3010EnergySupply>
|
||||
<D301010photovoltaic_system>
|
||||
<initial_investment cost_unit="currency/m2"> 800 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 800 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D301010photovoltaic_system>
|
||||
</D3010EnergySupply>
|
||||
<D3020Heatgeneratingsystems>
|
||||
<initial_investment cost_unit="currency/kW"> 622.86 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 622.86 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
|
||||
</D3020Heatgeneratingsystems>
|
||||
<D3030Coolinggenerationsystems>
|
||||
<initial_investment cost_unit="currency/kW"> 622.86 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 622.86 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3030Coolinggenerationsystems>
|
||||
<D3040Distributionsystems>
|
||||
<initial_investment cost_unit="currency/kW"> 0 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3040Distributionsystems>
|
||||
<D3060Controlsandinstrumentation>
|
||||
<initial_investment cost_unit="currency/kW"> 0 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3060Controlsandinstrumentation>
|
||||
<D3080OtherHVAC_AHU>
|
||||
<initial_investment cost_unit="currency/kW"> 47.62 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 47.62 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</D3080OtherHVAC_AHU>
|
||||
</D30HVAC>
|
||||
<D50Electrical>
|
||||
<D5010Electricalservicesanddistribution>
|
||||
<initial_investment cost_unit="currency/m2"> 171.43 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 171.43 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</D5010Electricalservicesanddistribution>
|
||||
<D5020Lightingandbranchwiring>
|
||||
<initial_investment cost_unit="currency/kW"> 139 </initial_investment>
|
||||
<reposition cost_unit="currency/kW"> 139 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
|
||||
</D5020Lightingandbranchwiring>
|
||||
</D50Electrical>
|
||||
</DServices>
|
||||
<EEquimentsandfurnishing>
|
||||
<E10Equipments>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</E10Equipments>
|
||||
<E10Furnishing>
|
||||
<initial_investment cost_unit="currency/m2"> 0 </initial_investment>
|
||||
<reposition cost_unit="currency/m2"> 0 </reposition>
|
||||
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
|
||||
</E10Furnishing>
|
||||
</EEquimentsandfurnishing>
|
||||
<engineer cost_unit="%"> 2.5 </engineer>
|
||||
</capital_cost>
|
||||
<operational_cost>
|
||||
<fuel fuel_type="electricity">
|
||||
<fixed>
|
||||
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
|
||||
</fixed>
|
||||
<variable_base cost_unit="currency/kWh"> hourlydatatable1 </variable_base>
|
||||
<variable_peak cost_unit="currency/kWh"> hourlydatatable2 </variable_peak>
|
||||
</fuel>
|
||||
<fuel fuel_type="gaz">
|
||||
<fixed>
|
||||
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
|
||||
</fixed>
|
||||
<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>
|
||||
<maintenance>
|
||||
<heating_equipment cost_unit="currency/kW"> 40 </heating_equipment>
|
||||
<cooling_equipment cost_unit="currency/kW"> 40 </cooling_equipment>
|
||||
<general_hvac_equipment cost_unit="currency/(m3/h)"> 0.05 </general_hvac_equipment>
|
||||
<photovoltaic_system cost_unit="currency/m2"> 1 </photovoltaic_system>
|
||||
<other_systems cost_unit="currency/m2"> 4.6 </other_systems>
|
||||
</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>
|
||||
<construction_subsidy cost_unit="%"> 2 </construction_subsidy>
|
||||
<hvac_subsidy cost_unit="%"> 1.5 </hvac_subsidy>
|
||||
<photovoltaic_subsidy cost_unit="%"> 3.6 </photovoltaic_subsidy>
|
||||
</subsidies>
|
||||
<energy_exports>
|
||||
<electricity cost_unit="currency/kWh"> hourlydatatable </electricity>
|
||||
<heat cost_unit="currency/kWh"> 0 </heat>
|
||||
</energy_exports>
|
||||
<tax_reductions>
|
||||
<reductions_taxes cost_unit="%"> 2 </reductions_taxes>
|
||||
</tax_reductions>
|
||||
<CO2_income cost_unit="currency/kgCO2exported"> 0 </CO2_income>
|
||||
</incomes>
|
||||
</archetype>
|
||||
</archetypes>
|
26456
hub/data/geolocation/cities15000.txt
Normal file
26456
hub/data/geolocation/cities15000.txt
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -4,13 +4,14 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Guillermo.GutierrezMorote@concordia.ca
|
||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
Soroush Samareh Abolhassani soroush.samarehabolhassani@mail.concordia.ca
|
||||
Oriol Gavaldà Torrellas oriol.gavalda@concordia.ca
|
||||
"""
|
||||
import copy
|
||||
from pathlib import Path
|
||||
from geomeppy import IDF
|
||||
import hub.helpers.constants as cte
|
||||
from hub.city_model_structure.attributes.schedule import Schedule
|
||||
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
|
||||
|
||||
|
||||
class Idf:
|
||||
|
@ -20,7 +21,9 @@ class Idf:
|
|||
_BUILDING = 'BUILDING'
|
||||
_ZONE = 'ZONE'
|
||||
_LIGHTS = 'LIGHTS'
|
||||
_APPLIANCES = 'OTHEREQUIPMENT'
|
||||
_PEOPLE = 'PEOPLE'
|
||||
_DHW = 'WATERUSE:EQUIPMENT'
|
||||
_THERMOSTAT = 'HVACTEMPLATE:THERMOSTAT'
|
||||
_IDEAL_LOAD_AIR_SYSTEM = 'HVACTEMPLATE:ZONE:IDEALLOADSAIRSYSTEM'
|
||||
_SURFACE = 'BUILDINGSURFACE:DETAILED'
|
||||
|
@ -36,6 +39,7 @@ class Idf:
|
|||
_WINDOW_MATERIAL_SIMPLE = 'WINDOWMATERIAL:SIMPLEGLAZINGSYSTEM'
|
||||
_ROUGHNESS = 'MediumRough'
|
||||
_INFILTRATION = 'ZONEINFILTRATION:DESIGNFLOWRATE'
|
||||
_VENTILATION = 'ZONEVENTILATION:DESIGNFLOWRATE'
|
||||
|
||||
_HOURLY_SCHEDULE = 'SCHEDULE:DAY:HOURLY'
|
||||
_COMPACT_SCHEDULE = 'SCHEDULE:COMPACT'
|
||||
|
@ -77,7 +81,7 @@ class Idf:
|
|||
}
|
||||
|
||||
def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path, export_type="Surfaces",
|
||||
target_buildings=None, adjacent_buildings=None):
|
||||
target_buildings=None):
|
||||
self._city = city
|
||||
self._output_path = str(output_path.resolve())
|
||||
self._output_file = str((output_path / f'{city.name}.idf').resolve())
|
||||
|
@ -93,11 +97,13 @@ class Idf:
|
|||
self._idf.newidfobject(self._SCHEDULE_LIMIT, Name=self._ON_OFF, Lower_Limit_Value=0, Upper_Limit_Value=1,
|
||||
Numeric_Type=self._DISCRETE)
|
||||
self._target_buildings = target_buildings
|
||||
self._adjacent_buildings = []
|
||||
if target_buildings is None:
|
||||
self._target_buildings = [building.name for building in self._city.buildings]
|
||||
self._adjacent_buildings = adjacent_buildings
|
||||
if self._adjacent_buildings is None:
|
||||
self._adjacent_buildings = []
|
||||
else:
|
||||
for building_name in target_buildings:
|
||||
building = city.city_object(building_name)
|
||||
self._adjacent_buildings += building.neighbours
|
||||
self._export()
|
||||
|
||||
@staticmethod
|
||||
|
@ -145,6 +151,72 @@ class Idf:
|
|||
Visible_Absorptance=layer.material.visible_absorptance
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _create_infiltration_schedules(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
|
||||
_schedule.data_type = cte.FRACTION
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.time_range = cte.DAY
|
||||
_schedule.day_types = copy.deepcopy(hvac_availability_schedule.day_types)
|
||||
_infiltration_values = []
|
||||
for hvac_value in hvac_availability_schedule.values:
|
||||
if hvac_value == 0:
|
||||
_infiltration_values.append(1.0)
|
||||
else:
|
||||
if thermal_zone.infiltration_rate_system_off == 0:
|
||||
_infiltration_values.append(0.0)
|
||||
else:
|
||||
_infiltration_values.append(
|
||||
thermal_zone.infiltration_rate_system_on / thermal_zone.infiltration_rate_system_off)
|
||||
_schedule.values = _infiltration_values
|
||||
_infiltration_schedules.append(_schedule)
|
||||
return _infiltration_schedules
|
||||
|
||||
@staticmethod
|
||||
def _create_yearly_values_schedules(schedule_type, values):
|
||||
_schedule = Schedule()
|
||||
_schedule.type = schedule_type
|
||||
_schedule.data_type = cte.ANY_NUMBER
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.time_range = cte.YEAR
|
||||
_schedule.day_types = ['monday',
|
||||
'tuesday',
|
||||
'wednesday',
|
||||
'thursday',
|
||||
'friday',
|
||||
'saturday',
|
||||
'sunday',
|
||||
'holiday',
|
||||
'winter_design_day',
|
||||
'summer_design_day']
|
||||
_schedule.values = values
|
||||
return [_schedule]
|
||||
|
||||
@staticmethod
|
||||
def _create_constant_value_schedules(schedule_type, value):
|
||||
_schedule = Schedule()
|
||||
_schedule.type = schedule_type
|
||||
_schedule.data_type = cte.ANY_NUMBER
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.time_range = cte.DAY
|
||||
_schedule.day_types = ['monday',
|
||||
'tuesday',
|
||||
'wednesday',
|
||||
'thursday',
|
||||
'friday',
|
||||
'saturday',
|
||||
'sunday',
|
||||
'holiday',
|
||||
'winter_design_day',
|
||||
'summer_design_day']
|
||||
_schedule.values = [value for _ in range(0, 24)]
|
||||
return [_schedule]
|
||||
|
||||
def _add_standard_compact_hourly_schedule(self, usage, schedule_type, schedules):
|
||||
for schedule in self._idf.idfobjects[self._COMPACT_SCHEDULE]:
|
||||
if schedule.Name == f'{schedule_type} schedules {usage}':
|
||||
|
@ -185,49 +257,9 @@ class Idf:
|
|||
_schedule.Interpolate_to_Timestep = 'No'
|
||||
_schedule.Minutes_per_Item = 60
|
||||
|
||||
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
|
||||
_schedule.data_type = cte.FRACTION
|
||||
_schedule.time_step = cte.HOUR
|
||||
_schedule.time_range = cte.DAY
|
||||
_schedule.day_types = copy.deepcopy(hvac_availability_schedule.day_types)
|
||||
_infiltration_values = []
|
||||
for hvac_value in hvac_availability_schedule.values:
|
||||
if hvac_value == 0:
|
||||
_infiltration_values.append(thermal_zone.infiltration_rate_system_off)
|
||||
else:
|
||||
_infiltration_values.append(thermal_zone.infiltration_rate_system_on)
|
||||
_schedule.values = _infiltration_values
|
||||
_infiltration_schedules.append(_schedule)
|
||||
for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
||||
if schedule.Name == f'Infiltration schedules {thermal_zone.usage_name}':
|
||||
return
|
||||
return self._add_standard_compact_hourly_schedule(thermal_zone.usage_name, 'Infiltration', _infiltration_schedules)
|
||||
|
||||
def _add_people_activity_level_schedules(self, thermal_zone):
|
||||
_occ = thermal_zone.occupancy
|
||||
if _occ.occupancy_density == 0:
|
||||
_total_heat = 0
|
||||
else:
|
||||
_total_heat = (_occ.sensible_convective_internal_gain + _occ.sensible_radiative_internal_gain
|
||||
+ _occ.latent_internal_gain) / _occ.occupancy_density
|
||||
for schedule in self._idf.idfobjects[self._COMPACT_SCHEDULE]:
|
||||
if schedule.Name == f'Activity Level schedules {thermal_zone.usage_name}':
|
||||
return
|
||||
_kwargs = {'Name': f'Activity Level schedules {thermal_zone.usage_name}',
|
||||
'Schedule_Type_Limits_Name': self.idf_type_limits[cte.ANY_NUMBER],
|
||||
'Field_1': 'Through: 12/31',
|
||||
'Field_2': 'For AllDays',
|
||||
'Field_3': f'Until: 24:00,{_total_heat}'}
|
||||
self._idf.newidfobject(self._COMPACT_SCHEDULE, **_kwargs)
|
||||
return
|
||||
|
||||
def _add_schedules(self, usage, schedule_type, new_schedules):
|
||||
if len(new_schedules) < 1:
|
||||
return
|
||||
schedule_from_file = False
|
||||
for schedule in new_schedules:
|
||||
if len(schedule.values) > 168: # Hours in one week
|
||||
|
@ -276,7 +308,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)
|
||||
|
@ -293,7 +325,6 @@ class Idf:
|
|||
for zone in self._idf.idfobjects['ZONE']:
|
||||
if zone.Name == name:
|
||||
return
|
||||
# todo: what do we need to define a zone in energy plus?
|
||||
self._idf.newidfobject(self._ZONE, Name=name, Volume=thermal_zone.volume)
|
||||
self._add_heating_system(thermal_zone, name)
|
||||
|
||||
|
@ -302,7 +333,6 @@ class Idf:
|
|||
for thermostat in self._idf.idfobjects[self._THERMOSTAT]:
|
||||
if thermostat.Name == thermostat_name:
|
||||
return thermostat
|
||||
# todo: change schedules to schedule name and create schedules using the add_schedule function
|
||||
return self._idf.newidfobject(self._THERMOSTAT,
|
||||
Name=thermostat_name,
|
||||
Heating_Setpoint_Schedule_Name=f'Heating thermostat schedules {thermal_zone.usage_name}',
|
||||
|
@ -338,6 +368,43 @@ class Idf:
|
|||
Activity_Level_Schedule_Name=f'Activity Level schedules {thermal_zone.usage_name}'
|
||||
)
|
||||
|
||||
def _add_lighting(self, thermal_zone: ThermalZone, zone_name: str):
|
||||
fraction_radiant = thermal_zone.lighting.radiative_fraction
|
||||
method = 'Watts/Area'
|
||||
storeys_number = int(thermal_zone.total_floor_area / thermal_zone.footprint_area)
|
||||
watts_per_zone_floor_area = thermal_zone.lighting.density * storeys_number
|
||||
subcategory = f'ELECTRIC EQUIPMENT#{zone_name}#GeneralLights'
|
||||
|
||||
self._idf.newidfobject(self._LIGHTS,
|
||||
Name=f'{zone_name}_lights',
|
||||
Zone_or_ZoneList_Name=zone_name,
|
||||
Schedule_Name=f'Lighting schedules {thermal_zone.usage_name}',
|
||||
Design_Level_Calculation_Method=method,
|
||||
Watts_per_Zone_Floor_Area=watts_per_zone_floor_area,
|
||||
Fraction_Radiant=fraction_radiant,
|
||||
EndUse_Subcategory=subcategory
|
||||
)
|
||||
|
||||
def _add_appliances(self, thermal_zone, zone_name):
|
||||
fuel_type = 'Electricity'
|
||||
fraction_radiant = thermal_zone.appliances.radiative_fraction
|
||||
fraction_latent = thermal_zone.appliances.latent_fraction
|
||||
method = 'Watts/Area'
|
||||
storeys_number = int(thermal_zone.total_floor_area / thermal_zone.footprint_area)
|
||||
watts_per_zone_floor_area = thermal_zone.appliances.density * storeys_number
|
||||
subcategory = f'ELECTRIC EQUIPMENT#{zone_name}#InteriorEquipment'
|
||||
self._idf.newidfobject(self._APPLIANCES,
|
||||
Fuel_Type=fuel_type,
|
||||
Name=f'{zone_name}_appliance',
|
||||
Zone_or_ZoneList_Name=zone_name,
|
||||
Schedule_Name=f'Appliance schedules {thermal_zone.usage_name}',
|
||||
Design_Level_Calculation_Method=method,
|
||||
Power_per_Zone_Floor_Area=watts_per_zone_floor_area,
|
||||
Fraction_Latent=fraction_latent,
|
||||
Fraction_Radiant=fraction_radiant,
|
||||
EndUse_Subcategory=subcategory
|
||||
)
|
||||
|
||||
def _add_infiltration(self, thermal_zone, zone_name):
|
||||
|
||||
for zone in self._idf.idfobjects["ZONE"]:
|
||||
|
@ -351,7 +418,36 @@ class Idf:
|
|||
Zone_or_ZoneList_Name=zone_name,
|
||||
Schedule_Name=schedule,
|
||||
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
||||
Air_Changes_per_Hour=thermal_zone.mechanical_air_change
|
||||
Air_Changes_per_Hour=thermal_zone.infiltration_rate_system_off
|
||||
)
|
||||
|
||||
def _add_ventilation(self, thermal_zone, zone_name):
|
||||
# for zone in self._idf.idfobjects["ZONE"]:
|
||||
# if zone.Name == f'{zone_name}_infiltration':
|
||||
# return
|
||||
schedule = f'Ventilation schedules {thermal_zone.usage_name}'
|
||||
# if schedule not in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
||||
# return
|
||||
# todo: revise ventilation with Pilar
|
||||
self._idf.newidfobject(self._VENTILATION,
|
||||
Name=f'{zone_name}_ventilation',
|
||||
Zone_or_ZoneList_Name=zone_name,
|
||||
Schedule_Name=schedule,
|
||||
Design_Flow_Rate_Calculation_Method='Flow/Zone',
|
||||
Flow_Rate_per_Zone_Floor_Area=thermal_zone.infiltration_rate_system_off
|
||||
)
|
||||
|
||||
def _add_dhw(self, thermal_zone, zone_name):
|
||||
peak_flow_rate = thermal_zone.domestic_hot_water.peak_flow * thermal_zone.total_floor_area
|
||||
self._idf.newidfobject(self._DHW,
|
||||
Name=f'DHW {zone_name}',
|
||||
Peak_Flow_Rate=peak_flow_rate,
|
||||
Flow_Rate_Fraction_Schedule_Name=f'DHW_prof schedules {thermal_zone.usage_name}',
|
||||
Target_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}',
|
||||
Hot_Water_Supply_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}',
|
||||
Cold_Water_Supply_Temperature_Schedule_Name=f'cold_temp schedules {zone_name}',
|
||||
EndUse_Subcategory=f'DHW {zone_name}',
|
||||
Zone_Name=zone_name
|
||||
)
|
||||
|
||||
def _rename_building(self, city_name):
|
||||
|
@ -395,21 +491,36 @@ class Idf:
|
|||
self._add_window_construction_and_material(thermal_opening)
|
||||
usage = thermal_zone.usage_name
|
||||
if building.name in self._target_buildings or building.name in self._adjacent_buildings:
|
||||
self._add_infiltration_schedules(thermal_zone)
|
||||
if thermal_zone.occupancy is not None:
|
||||
self._add_schedules(usage, 'Occupancy', thermal_zone.occupancy.occupancy_schedules)
|
||||
self._add_people_activity_level_schedules(thermal_zone)
|
||||
self._add_occupancy(thermal_zone, building.name)
|
||||
|
||||
if thermal_zone.thermal_control is not None:
|
||||
self._add_schedules(usage, 'HVAC AVAIL', thermal_zone.thermal_control.hvac_availability_schedules)
|
||||
self._add_schedules(usage, 'Heating thermostat', thermal_zone.thermal_control.heating_set_point_schedules)
|
||||
self._add_schedules(usage, 'Cooling thermostat', thermal_zone.thermal_control.cooling_set_point_schedules)
|
||||
|
||||
_new_schedules = self._create_infiltration_schedules(thermal_zone)
|
||||
self._add_schedules(usage, 'Infiltration', _new_schedules)
|
||||
self._add_schedules(usage, 'Occupancy', thermal_zone.occupancy.occupancy_schedules)
|
||||
self._add_schedules(usage, 'HVAC AVAIL', thermal_zone.thermal_control.hvac_availability_schedules)
|
||||
self._add_schedules(usage, 'Heating thermostat', thermal_zone.thermal_control.heating_set_point_schedules)
|
||||
self._add_schedules(usage, 'Cooling thermostat', thermal_zone.thermal_control.cooling_set_point_schedules)
|
||||
self._add_schedules(usage, 'Lighting', thermal_zone.lighting.schedules)
|
||||
self._add_schedules(usage, 'Appliance', thermal_zone.appliances.schedules)
|
||||
self._add_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules)
|
||||
_new_schedules = self._create_yearly_values_schedules('cold_temp',
|
||||
building.cold_water_temperature[cte.HOUR]['epw'])
|
||||
self._add_schedules(building.name, 'cold_temp', _new_schedules)
|
||||
value = thermal_zone.domestic_hot_water.service_temperature
|
||||
_new_schedules = self._create_constant_value_schedules('DHW_temp', value)
|
||||
self._add_schedules(usage, 'DHW_temp', _new_schedules)
|
||||
_occ = thermal_zone.occupancy
|
||||
if _occ.occupancy_density == 0:
|
||||
_total_heat = 0
|
||||
else:
|
||||
_total_heat = (_occ.sensible_convective_internal_gain + _occ.sensible_radiative_internal_gain
|
||||
+ _occ.latent_internal_gain) / _occ.occupancy_density
|
||||
_new_schedules = self._create_constant_value_schedules('Activity Level', _total_heat)
|
||||
self._add_schedules(usage, 'Activity Level', _new_schedules)
|
||||
self._add_zone(thermal_zone, building.name)
|
||||
self._add_heating_system(thermal_zone, building.name)
|
||||
self._add_infiltration(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:
|
||||
if building.internal_zones[0].thermal_zones is not None:
|
||||
|
@ -420,27 +531,24 @@ class Idf:
|
|||
self._add_shading(building)
|
||||
else:
|
||||
self._add_block(building)
|
||||
# todo: this should change to specific variables per zone to process only the ones in the buildings_to_calculate
|
||||
for building in self._target_buildings:
|
||||
continue
|
||||
|
||||
self._idf.newidfobject(
|
||||
"OUTPUT:VARIABLE",
|
||||
Variable_Name="Zone Ideal Loads Supply Air Total Heating Energy",
|
||||
Reporting_Frequency="Hourly",
|
||||
)
|
||||
"OUTPUT:VARIABLE",
|
||||
Variable_Name="Zone Ideal Loads Supply Air Total Heating Energy",
|
||||
Reporting_Frequency="Monthly",
|
||||
)
|
||||
|
||||
self._idf.newidfobject(
|
||||
"OUTPUT:VARIABLE",
|
||||
Variable_Name="Zone Ideal Loads Supply Air Total Cooling Energy",
|
||||
Reporting_Frequency="Hourly",
|
||||
)
|
||||
self._idf.match()
|
||||
try:
|
||||
self._idf.intersect_match()
|
||||
except IndexError:
|
||||
# seems to be a bug from geomeppy when surfaces cannot be intersected
|
||||
pass
|
||||
"OUTPUT:VARIABLE",
|
||||
Variable_Name="Zone Ideal Loads Supply Air Total Cooling Energy",
|
||||
Reporting_Frequency="Monthly",
|
||||
)
|
||||
|
||||
self._idf.newidfobject(
|
||||
"OUTPUT:VARIABLE",
|
||||
Variable_Name="Water Use Equipment Heating Rate",
|
||||
Reporting_Frequency="Monthly",
|
||||
)
|
||||
|
||||
# post-process to erase windows associated to adiabatic walls
|
||||
windows_list = []
|
||||
|
@ -495,20 +603,29 @@ class Idf:
|
|||
|
||||
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'
|
||||
idf_surface_type = self.idf_surfaces[surface.type]
|
||||
_kwargs = {'Name': f'{surface.name}',
|
||||
'Surface_Type': idf_surface_type,
|
||||
'Zone_Name': zone_name}
|
||||
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)
|
||||
if surface.percentage_shared is not None and surface.percentage_shared > 0.5:
|
||||
outside_boundary_condition = 'Surface'
|
||||
outside_boundary_condition_object = surface.name
|
||||
sun_exposure = 'NoSun'
|
||||
wind_exposure = 'NoWind'
|
||||
_kwargs['Outside_Boundary_Condition_Object'] = outside_boundary_condition_object
|
||||
|
||||
_kwargs['Outside_Boundary_Condition'] = outside_boundary_condition
|
||||
_kwargs['Sun_Exposure'] = sun_exposure
|
||||
_kwargs['Wind_Exposure'] = wind_exposure
|
||||
idf_surface = self._idf.newidfobject(self._SURFACE, **_kwargs)
|
||||
|
||||
coordinates = self._matrix_to_list(surface.solid_polygon.coordinates,
|
||||
self._city.lower_corner)
|
||||
idf_surface.setcoords(coordinates)
|
||||
|
@ -530,21 +647,31 @@ class Idf:
|
|||
outside_boundary_condition = 'Outdoors'
|
||||
sun_exposure = 'SunExposed'
|
||||
wind_exposure = 'WindExposed'
|
||||
_kwargs = {'Name': f'{boundary.parent_surface.name}',
|
||||
'Surface_Type': idf_surface_type,
|
||||
'Zone_Name': zone_name}
|
||||
if boundary.parent_surface.type == cte.GROUND:
|
||||
outside_boundary_condition = 'Ground'
|
||||
sun_exposure = 'NoSun'
|
||||
wind_exposure = 'NoWind'
|
||||
if boundary.parent_surface.percentage_shared is not None and boundary.parent_surface.percentage_shared >= 0.5:
|
||||
outside_boundary_condition = 'Surface'
|
||||
outside_boundary_condition_object = boundary.parent_surface.name
|
||||
sun_exposure = 'NoSun'
|
||||
wind_exposure = 'NoWind'
|
||||
_kwargs['Outside_Boundary_Condition_Object'] = outside_boundary_condition_object
|
||||
_kwargs['Outside_Boundary_Condition'] = outside_boundary_condition
|
||||
_kwargs['Sun_Exposure'] = sun_exposure
|
||||
_kwargs['Wind_Exposure'] = wind_exposure
|
||||
|
||||
if boundary.parent_surface.vegetation is not None:
|
||||
construction_name = f'{boundary.construction_name}_{boundary.parent_surface.vegetation.name}'
|
||||
else:
|
||||
construction_name = boundary.construction_name
|
||||
surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.parent_surface.name}',
|
||||
Surface_Type=idf_surface_type,
|
||||
Zone_Name=zone_name,
|
||||
Construction_Name=construction_name,
|
||||
Outside_Boundary_Condition=outside_boundary_condition,
|
||||
Sun_Exposure=sun_exposure,
|
||||
Wind_Exposure=wind_exposure)
|
||||
_kwargs['Construction_Name'] = construction_name
|
||||
|
||||
surface = self._idf.newidfobject(self._SURFACE, **_kwargs)
|
||||
|
||||
coordinates = self._matrix_to_list(boundary.parent_surface.solid_polygon.coordinates,
|
||||
self._city.lower_corner)
|
||||
surface.setcoords(coordinates)
|
||||
|
@ -570,7 +697,7 @@ class Idf:
|
|||
for material in self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]:
|
||||
if material['Name'] == glazing:
|
||||
if material['UFactor'] == opening.overall_u_value and \
|
||||
material['Solar_Heat_Gain_Coefficient'] == opening.g_value:
|
||||
material['Solar_Heat_Gain_Coefficient'] == opening.g_value:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
|
@ -127,26 +127,31 @@
|
|||
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:Meter,DISTRICTHEATING:Facility,monthly;
|
||||
Output:Meter,DISTRICTCOOLING:Facility,monthly;
|
||||
Output:Meter,InteriorEquipment:Electricity,monthly;
|
||||
Output:Meter,InteriorLights:Electricity,monthly;
|
||||
|
||||
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:Diagnostics,DisplayUnusedSchedules;
|
||||
OutputControl:IlluminanceMap:Style,
|
||||
Comma; !- Column separator
|
||||
|
|
|
@ -51,6 +51,7 @@ class InselMonthlyEnergyBalance(Insel):
|
|||
)
|
||||
self._export()
|
||||
|
||||
|
||||
def _export(self):
|
||||
for i_file, content in enumerate(self._contents):
|
||||
file_name = self._insel_files_paths[i_file]
|
||||
|
@ -62,8 +63,8 @@ class InselMonthlyEnergyBalance(Insel):
|
|||
levels_of_detail = self._city.level_of_detail
|
||||
if levels_of_detail.geometry is None:
|
||||
raise Exception(f'Level of detail of geometry not assigned')
|
||||
if levels_of_detail.geometry < 1:
|
||||
raise Exception(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 1')
|
||||
if levels_of_detail.geometry < 0.5:
|
||||
raise Exception(f'Level of detail of geometry = {levels_of_detail.geometry}. Required minimum level 0.5')
|
||||
if levels_of_detail.construction is None:
|
||||
raise Exception(f'Level of detail of construction not assigned')
|
||||
if levels_of_detail.construction < 1:
|
||||
|
@ -94,12 +95,19 @@ class InselMonthlyEnergyBalance(Insel):
|
|||
inputs.append(f"{str(100 + i)}.1 % Radiation surface {str(i)}")
|
||||
|
||||
number_of_storeys = int(building.eave_height / building.average_storey_height)
|
||||
attic_heated = building.attic_heated
|
||||
basement_heated = building.basement_heated
|
||||
if building.attic_heated is None:
|
||||
attic_heated = 0
|
||||
if building.basement_heated is None:
|
||||
basement_heated = 0
|
||||
|
||||
# BUILDING PARAMETERS
|
||||
parameters = [f'{building.volume} % BP(1) Heated Volume (m3)',
|
||||
f'{building.average_storey_height} % BP(2) Average storey height (m)',
|
||||
f'{number_of_storeys} % BP(3) Number of storeys above ground',
|
||||
f'{building.attic_heated} % BP(4) Attic heating type (0=no room, 1=unheated, 2=heated)',
|
||||
f'{building.basement_heated} % BP(5) Cellar heating type (0=no room, 1=unheated, 2=heated, '
|
||||
f'{attic_heated} % BP(4) Attic heating type (0=no room, 1=unheated, 2=heated)',
|
||||
f'{basement_heated} % BP(5) Cellar heating type (0=no room, 1=unheated, 2=heated, '
|
||||
f'99=invalid)']
|
||||
|
||||
# todo: this method and the insel model have to be reviewed for more than one internal zone
|
||||
|
|
|
@ -17,7 +17,7 @@ class EnergyBuildingsExportsFactory:
|
|||
"""
|
||||
Energy Buildings exports factory class
|
||||
"""
|
||||
def __init__(self, export_type, city, path, target_buildings=None, adjacent_buildings=None):
|
||||
def __init__(self, export_type, city, path, target_buildings=None):
|
||||
self._city = city
|
||||
self._export_type = '_' + export_type.lower()
|
||||
class_funcs = validate_import_export_type(EnergyBuildingsExportsFactory)
|
||||
|
@ -29,7 +29,6 @@ class EnergyBuildingsExportsFactory:
|
|||
path = Path(path)
|
||||
self._path = path
|
||||
self._target_buildings = target_buildings
|
||||
self._adjacent_buildings = adjacent_buildings
|
||||
|
||||
@property
|
||||
def _energy_ade(self):
|
||||
|
@ -56,7 +55,7 @@ class EnergyBuildingsExportsFactory:
|
|||
# todo: create a get epw file function based on the city
|
||||
weather_path = (Path(__file__).parent / '../data/weather/epw/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
|
||||
return Idf(self._city, self._path, (idf_data_path / 'Minimal.idf'), (idf_data_path / 'Energy+.idd'), weather_path,
|
||||
target_buildings=self._target_buildings, adjacent_buildings=self._adjacent_buildings)
|
||||
target_buildings=self._target_buildings)
|
||||
|
||||
@property
|
||||
def _insel_monthly_energy_balance(self):
|
||||
|
|
|
@ -65,14 +65,6 @@ class ExportsFactory:
|
|||
"""
|
||||
return Obj(self._city, self._path)
|
||||
|
||||
@property
|
||||
def _grounded_obj(self):
|
||||
"""
|
||||
Export the city geometry to obj with grounded coordinates
|
||||
:return: None
|
||||
"""
|
||||
return Obj(self._city, self._path)
|
||||
|
||||
@property
|
||||
def _sra(self):
|
||||
"""
|
||||
|
|
|
@ -4,6 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
import xmltodict
|
||||
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
|
@ -32,9 +34,12 @@ class SimplifiedRadiosityAlgorithm:
|
|||
self._end_month = end_month
|
||||
self._end_day = end_day
|
||||
self._city = city
|
||||
self._city.climate_file = str((Path(file_name).parent / f'{city.name}.cli').resolve())
|
||||
self._city.climate_reference_city = city.location
|
||||
self._target_buildings = target_buildings
|
||||
self._weather_format = weather_format
|
||||
self._weather_file = weather_file
|
||||
|
||||
self._export()
|
||||
|
||||
def _correct_point(self, point):
|
||||
|
@ -45,8 +50,8 @@ class SimplifiedRadiosityAlgorithm:
|
|||
return [x, y, z]
|
||||
|
||||
def _export(self):
|
||||
self._export_sra_xml()
|
||||
self._export_sra_cli()
|
||||
self._export_sra_xml()
|
||||
|
||||
def _export_sra_cli(self):
|
||||
file = self._city.climate_file
|
||||
|
|
|
@ -184,6 +184,7 @@ MIN_FLOAT = float('-inf')
|
|||
# Tools
|
||||
SRA = 'sra'
|
||||
INSEL_MEB = 'insel meb'
|
||||
PEAK_LOAD = 'peak load'
|
||||
|
||||
# Costs units
|
||||
CURRENCY_PER_SQM = 'currency/m2'
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
Dictionaries module for hub function to Montreal custom costs function
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class HubFunctionToMontrealCustomCostsFunction:
|
||||
|
||||
def __init__(self):
|
||||
self._dictionary = {
|
||||
cte.RESIDENTIAL: 'residential',
|
||||
cte.SINGLE_FAMILY_HOUSE: 'residential',
|
||||
cte.MULTI_FAMILY_HOUSE: 'residential',
|
||||
cte.ROW_HOUSE: 'residential',
|
||||
cte.MID_RISE_APARTMENT: 'residential',
|
||||
cte.HIGH_RISE_APARTMENT: 'residential',
|
||||
cte.OFFICE_AND_ADMINISTRATION: 'non-residential',
|
||||
cte.SMALL_OFFICE: 'non-residential',
|
||||
cte.MEDIUM_OFFICE: 'non-residential',
|
||||
cte.LARGE_OFFICE: 'non-residential',
|
||||
cte.COURTHOUSE: 'non-residential',
|
||||
cte.FIRE_STATION: 'non-residential',
|
||||
cte.PENITENTIARY: 'non-residential',
|
||||
cte.POLICE_STATION: 'non-residential',
|
||||
cte.POST_OFFICE: 'non-residential',
|
||||
cte.LIBRARY: 'non-residential',
|
||||
cte.EDUCATION: 'non-residential',
|
||||
cte.PRIMARY_SCHOOL: 'non-residential',
|
||||
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'non-residential',
|
||||
cte.SECONDARY_SCHOOL: 'non-residential',
|
||||
cte.UNIVERSITY: 'non-residential',
|
||||
cte.LABORATORY_AND_RESEARCH_CENTER: 'non-residential',
|
||||
cte.STAND_ALONE_RETAIL: 'non-residential',
|
||||
cte.HOSPITAL: 'non-residential',
|
||||
cte.OUT_PATIENT_HEALTH_CARE: 'non-residential',
|
||||
cte.HEALTH_CARE: 'non-residential',
|
||||
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'non-residential',
|
||||
cte.COMMERCIAL: 'non-residential',
|
||||
cte.STRIP_MALL: 'non-residential',
|
||||
cte.SUPERMARKET: 'non-residential',
|
||||
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'non-residential',
|
||||
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'non-residential',
|
||||
cte.RESTAURANT: 'full service restaurant',
|
||||
cte.QUICK_SERVICE_RESTAURANT: 'non-residential',
|
||||
cte.FULL_SERVICE_RESTAURANT: 'non-residential',
|
||||
cte.HOTEL: 'non-residential',
|
||||
cte.HOTEL_MEDIUM_CLASS: 'non-residential',
|
||||
cte.SMALL_HOTEL: 'non-residential',
|
||||
cte.LARGE_HOTEL: 'non-residential',
|
||||
cte.DORMITORY: 'non-residential',
|
||||
cte.EVENT_LOCATION: 'non-residential',
|
||||
cte.CONVENTION_CENTER: 'non-residential',
|
||||
cte.HALL: 'non-residential',
|
||||
cte.GREEN_HOUSE: 'non-residential',
|
||||
cte.INDUSTRY: 'non-residential',
|
||||
cte.WORKSHOP: 'non-residential',
|
||||
cte.WAREHOUSE: 'non-residential',
|
||||
cte.WAREHOUSE_REFRIGERATED: 'non-residential',
|
||||
cte.SPORTS_LOCATION: 'non-residential',
|
||||
cte.SPORTS_ARENA: 'non-residential',
|
||||
cte.GYMNASIUM: 'non-residential',
|
||||
cte.MOTION_PICTURE_THEATRE: 'non-residential',
|
||||
cte.MUSEUM: 'non-residential',
|
||||
cte.PERFORMING_ARTS_THEATRE: 'non-residential',
|
||||
cte.TRANSPORTATION: 'non-residential',
|
||||
cte.AUTOMOTIVE_FACILITY: 'non-residential',
|
||||
cte.PARKING_GARAGE: 'non-residential',
|
||||
cte.RELIGIOUS: 'non-residential',
|
||||
cte.NON_HEATED: 'non-residential'
|
||||
}
|
||||
|
||||
@property
|
||||
def dictionary(self) -> dict:
|
||||
return self._dictionary
|
|
@ -67,7 +67,7 @@ class HubFunctionToNrelConstructionFunction:
|
|||
cte.MUSEUM: 'n/a',
|
||||
cte.PERFORMING_ARTS_THEATRE: 'n/a',
|
||||
cte.TRANSPORTATION: 'n/a',
|
||||
cte.AUTOMOTIVE_FACILITY: 'n/aquebec_to_hub',
|
||||
cte.AUTOMOTIVE_FACILITY: 'n/a',
|
||||
cte.PARKING_GARAGE: 'n/a',
|
||||
cte.RELIGIOUS: 'n/a',
|
||||
cte.NON_HEATED: 'n/a'
|
||||
|
|
|
@ -14,6 +14,7 @@ from hub.helpers.data.hub_function_to_nrcan_construction_function import HubFunc
|
|||
from hub.helpers.data.hub_usage_to_comnet_usage import HubUsageToComnetUsage
|
||||
from hub.helpers.data.hub_usage_to_hft_usage import HubUsageToHftUsage
|
||||
from hub.helpers.data.hub_usage_to_nrcan_usage import HubUsageToNrcanUsage
|
||||
from hub.helpers.data.hub_function_to_montreal_custom_costs_function import HubFunctionToMontrealCustomCostsFunction
|
||||
|
||||
|
||||
class Dictionaries:
|
||||
|
@ -91,3 +92,11 @@ class Dictionaries:
|
|||
"""
|
||||
return AlkisFunctionToHubFunction().dictionary
|
||||
|
||||
@property
|
||||
def hub_function_to_montreal_custom_costs_function(self) -> dict:
|
||||
"""
|
||||
Get hub function to Montreal custom costs function, transformation dictionary
|
||||
:return: dict
|
||||
"""
|
||||
return HubFunctionToMontrealCustomCostsFunction().dictionary
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
|||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import requests
|
||||
from PIL import Image
|
||||
from trimesh import Trimesh
|
||||
from trimesh import intersections
|
||||
|
@ -55,16 +55,22 @@ class GeometryHelper:
|
|||
'urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH': 'epsg:25832'
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def factor():
|
||||
return 0.5
|
||||
|
||||
def __init__(self, delta=0, area_delta=0):
|
||||
self._delta = delta
|
||||
self._area_delta = area_delta
|
||||
|
||||
@staticmethod
|
||||
def coordinate_to_map_point(coordinate, city):
|
||||
return MapPoint(((city.upper_corner[0] - coordinate[0]) * 0.5), ((city.upper_corner[1] - coordinate[1]) * 0.5))
|
||||
factor = GeometryHelper.factor()
|
||||
return MapPoint(((coordinate[0] - city.lower_corner[0]) * factor), ((coordinate[1] - city.lower_corner[1]) * factor))
|
||||
|
||||
@staticmethod
|
||||
def city_mapping(city, building_names=None, plot=False):
|
||||
|
||||
"""
|
||||
|
||||
Returns a shared_information dictionary like
|
||||
|
@ -75,8 +81,9 @@ class GeometryHelper:
|
|||
lines_information = {}
|
||||
if building_names is None:
|
||||
building_names = [b.name for b in city.buildings]
|
||||
x = int((city.upper_corner[0] - city.lower_corner[0]) * 0.5) + 1
|
||||
y = int((city.upper_corner[1] - city.lower_corner[1]) * 0.5) + 1
|
||||
factor = GeometryHelper.factor()
|
||||
x = math.ceil((city.upper_corner[0] - city.lower_corner[0]) * factor) + 1
|
||||
y = math.ceil((city.upper_corner[1] - city.lower_corner[1]) * factor) + 1
|
||||
city_map = [['' for _ in range(y + 1)] for _ in range(x + 1)]
|
||||
map_info = [[{} for _ in range(y + 1)] for _ in range(x + 1)]
|
||||
img = Image.new('RGB', (x + 1, y + 1), "black") # create a new black image
|
||||
|
@ -92,15 +99,18 @@ class GeometryHelper:
|
|||
if i == length:
|
||||
j = 0
|
||||
next_coordinate = ground.perimeter_polygon.coordinates[j]
|
||||
point = GeometryHelper.coordinate_to_map_point(coordinate, city)
|
||||
distance = int(GeometryHelper.distance_between_points(coordinate, next_coordinate))
|
||||
if distance == 0:
|
||||
distance = GeometryHelper.distance_between_points(coordinate, next_coordinate)
|
||||
steps = int(distance * factor * 2)
|
||||
if steps == 0:
|
||||
continue
|
||||
delta_x = (coordinate[0] - next_coordinate[0]) / (distance / 0.5)
|
||||
delta_y = (coordinate[1] - next_coordinate[1]) / (distance / 0.5)
|
||||
for k in range(0, distance):
|
||||
x = MapPoint(point.x + (delta_x * k), point.y + (delta_y * k)).x
|
||||
y = MapPoint(point.x + (delta_x * k), point.y + (delta_y * k)).y
|
||||
delta_x = (next_coordinate[0] - coordinate[0]) / steps
|
||||
delta_y = (next_coordinate[1] - coordinate[1]) / steps
|
||||
|
||||
for k in range(0, steps):
|
||||
new_coordinate = (coordinate[0] + (delta_x * k), coordinate[1] + (delta_y * k))
|
||||
point = GeometryHelper.coordinate_to_map_point(new_coordinate, city)
|
||||
x = point.x
|
||||
y = point.y
|
||||
if city_map[x][y] == '':
|
||||
city_map[x][y] = building.name
|
||||
map_info[x][y] = {
|
||||
|
@ -172,48 +182,6 @@ class GeometryHelper:
|
|||
img.show()
|
||||
return lines_information
|
||||
|
||||
@staticmethod
|
||||
def fast_city_mapping(city, building_names=None):
|
||||
lines_information = {}
|
||||
if building_names is None:
|
||||
building_names = [b.name for b in city.buildings]
|
||||
x = int((city.upper_corner[0] - city.lower_corner[0]) * 0.5) + 1
|
||||
y = int((city.upper_corner[1] - city.lower_corner[1]) * 0.5) + 1
|
||||
city_map = [['' for _ in range(y + 1)] for _ in range(x + 1)]
|
||||
for building_name in building_names:
|
||||
building = city.city_object(building_name)
|
||||
line = 0
|
||||
for ground in building.grounds:
|
||||
length = len(ground.perimeter_polygon.coordinates) - 1
|
||||
for i, coordinate in enumerate(ground.perimeter_polygon.coordinates):
|
||||
j = i + 1
|
||||
if i == length:
|
||||
j = 0
|
||||
next_coordinate = ground.perimeter_polygon.coordinates[j]
|
||||
point = GeometryHelper.coordinate_to_map_point(coordinate, city)
|
||||
distance = int(GeometryHelper.distance_between_points(coordinate, next_coordinate))
|
||||
if distance == 0:
|
||||
continue
|
||||
delta_x = (coordinate[0] - next_coordinate[0]) / (distance / 0.5)
|
||||
delta_y = (coordinate[1] - next_coordinate[1]) / (distance / 0.5)
|
||||
for k in range(0, distance):
|
||||
x = MapPoint(point.x + (delta_x * k), point.y + (delta_y * k)).x
|
||||
y = MapPoint(point.x + (delta_x * k), point.y + (delta_y * k)).y
|
||||
if city_map[x][y] == '':
|
||||
city_map[x][y] = building.name
|
||||
elif city_map[x][y] != building.name:
|
||||
neighbour = city.city_object(city_map[x][y])
|
||||
if building.neighbours is None:
|
||||
building.neighbours = [neighbour]
|
||||
elif neighbour not in building.neighbours:
|
||||
building.neighbours.append(neighbour)
|
||||
if neighbour.neighbours is None:
|
||||
neighbour.neighbours = [building]
|
||||
elif building not in neighbour.neighbours:
|
||||
neighbour.neighbours.append(building)
|
||||
line += 1
|
||||
return lines_information
|
||||
|
||||
@staticmethod
|
||||
def segment_list_to_trimesh(lines) -> Trimesh:
|
||||
"""
|
||||
|
@ -298,19 +266,24 @@ class GeometryHelper:
|
|||
"""
|
||||
Get Location from latitude and longitude
|
||||
"""
|
||||
url = 'https://nominatim.openstreetmap.org/reverse?lat={latitude}&lon={longitude}&format=json'
|
||||
response = requests.get(url.format(latitude=latitude, longitude=longitude))
|
||||
if response.status_code != 200:
|
||||
# This means something went wrong.
|
||||
raise Exception('GET /tasks/ {}'.format(response.status_code))
|
||||
|
||||
response = response.json()
|
||||
_data_path = Path(Path(__file__).parent.parent / 'data/geolocation/cities15000.txt').resolve()
|
||||
latitude = float(latitude)
|
||||
longitude = float(longitude)
|
||||
distance = math.inf
|
||||
country = 'Unknown'
|
||||
city = 'Unknown'
|
||||
country = 'ca'
|
||||
if 'city' in response['address']:
|
||||
city = response['address']['city']
|
||||
if 'country_code' in response['address']:
|
||||
country = response['address']['country_code']
|
||||
with open(_data_path, 'r', encoding='utf-8') as f:
|
||||
for line_number, line in enumerate(f):
|
||||
fields = line.split('\t')
|
||||
file_city_name = fields[2]
|
||||
file_latitude = float(fields[4])
|
||||
file_longitude = float(fields[5])
|
||||
file_country_code = fields[8]
|
||||
new_distance = math.sqrt(pow((latitude - file_latitude), 2) + pow((longitude - file_longitude), 2))
|
||||
if distance > new_distance:
|
||||
distance = new_distance
|
||||
country = file_country_code
|
||||
city = file_city_name
|
||||
return Location(country, city)
|
||||
|
||||
@staticmethod
|
||||
|
|
0
hub/helpers/peak_calculation/__init__.py
Normal file
0
hub/helpers/peak_calculation/__init__.py
Normal file
118
hub/helpers/peak_calculation/loads_calculation.py
Normal file
118
hub/helpers/peak_calculation/loads_calculation.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
"""
|
||||
Calculation of loads for peak heating and cooling
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class LoadsCalculation:
|
||||
"""
|
||||
LoadsCalculation class
|
||||
"""
|
||||
def __init__(self, building):
|
||||
self._building = building
|
||||
|
||||
@staticmethod
|
||||
def _get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature, ground_temperature):
|
||||
load_transmitted_opaque = 0
|
||||
load_transmitted_transparent = 0
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
if thermal_boundary.type == cte.GROUND:
|
||||
external_temperature = ground_temperature
|
||||
elif thermal_boundary.type == cte.INTERIOR_WALL:
|
||||
external_temperature = internal_temperature
|
||||
else:
|
||||
external_temperature = ambient_temperature
|
||||
|
||||
load_transmitted_opaque += thermal_boundary.u_value * thermal_boundary.opaque_area \
|
||||
* (internal_temperature - external_temperature)
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
load_transmitted_transparent += thermal_opening.overall_u_value \
|
||||
* (internal_temperature - external_temperature)
|
||||
load_transmitted_opaque += thermal_zone.additional_thermal_bridge_u_value * thermal_zone.footprint_area \
|
||||
* (internal_temperature - ambient_temperature)
|
||||
load_transmitted = load_transmitted_opaque + load_transmitted_transparent
|
||||
return load_transmitted
|
||||
|
||||
@staticmethod
|
||||
def _get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature):
|
||||
load_renovation_sensible = 0
|
||||
for usage in thermal_zone.usages:
|
||||
load_renovation_sensible += cte.AIR_DENSITY * cte.AIR_HEAT_CAPACITY * usage.mechanical_air_change \
|
||||
* thermal_zone.volume / cte.HOUR_TO_MINUTES / cte.MINUTES_TO_SECONDS \
|
||||
* (internal_temperature - ambient_temperature)
|
||||
|
||||
load_infiltration_sensible = cte.AIR_DENSITY * cte.AIR_HEAT_CAPACITY * thermal_zone.infiltration_rate_system_off \
|
||||
* thermal_zone.volume / cte.HOUR_TO_MINUTES / cte.MINUTES_TO_SECONDS \
|
||||
* (internal_temperature - ambient_temperature)
|
||||
|
||||
load_ventilation = load_renovation_sensible + load_infiltration_sensible
|
||||
|
||||
return load_ventilation
|
||||
|
||||
def get_heating_transmitted_load(self, ambient_temperature, ground_temperature):
|
||||
heating_load_transmitted = 0
|
||||
for internal_zone in self._building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
internal_temperature = thermal_zone.thermal_control.mean_heating_set_point
|
||||
heating_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature,
|
||||
ground_temperature)
|
||||
return heating_load_transmitted
|
||||
|
||||
def get_cooling_transmitted_load(self, ambient_temperature, ground_temperature):
|
||||
cooling_load_transmitted = 0
|
||||
for internal_zone in self._building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point
|
||||
cooling_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature,
|
||||
ground_temperature)
|
||||
return cooling_load_transmitted
|
||||
|
||||
def get_heating_ventilation_load_sensible(self, ambient_temperature):
|
||||
heating_ventilation_load = 0
|
||||
for internal_zone in self._building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
internal_temperature = thermal_zone.thermal_control.mean_heating_set_point
|
||||
heating_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature)
|
||||
return heating_ventilation_load
|
||||
|
||||
def get_cooling_ventilation_load_sensible(self, ambient_temperature):
|
||||
cooling_ventilation_load = 0
|
||||
for internal_zone in self._building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point
|
||||
cooling_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature)
|
||||
return cooling_ventilation_load
|
||||
|
||||
def get_internal_load_sensible(self):
|
||||
cooling_load_occupancy_sensible = 0
|
||||
cooling_load_lighting = 0
|
||||
cooling_load_equipment_sensible = 0
|
||||
for internal_zone in self._building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
cooling_load_occupancy_sensible += (thermal_zone.occupancy.sensible_convective_internal_gain
|
||||
+ thermal_zone.occupancy.sensible_radiative_internal_gain) \
|
||||
* thermal_zone.footprint_area
|
||||
cooling_load_lighting += (thermal_zone.lighting.density * thermal_zone.lighting.convective_fraction
|
||||
+ thermal_zone.lighting.density * thermal_zone.lighting.radiative_fraction) \
|
||||
* thermal_zone.footprint_area
|
||||
cooling_load_equipment_sensible += (thermal_zone.appliances.density * thermal_zone.appliances.convective_fraction
|
||||
+ thermal_zone.appliances.density * thermal_zone.appliances.radiative_fraction) \
|
||||
* thermal_zone.footprint_area
|
||||
internal_load = cooling_load_occupancy_sensible + cooling_load_lighting + cooling_load_equipment_sensible
|
||||
return internal_load
|
||||
|
||||
def get_radiation_load(self, irradiance_format, hour):
|
||||
cooling_load_radiation = 0
|
||||
for internal_zone in self._building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
for thermal_opening in thermal_boundary.thermal_openings:
|
||||
radiation = thermal_boundary.parent_surface.global_irradiance[cte.HOUR][irradiance_format][hour]
|
||||
cooling_load_radiation += thermal_opening.area * (1 - thermal_opening.frame_ratio) * thermal_opening.g_value \
|
||||
* radiation
|
||||
return cooling_load_radiation
|
71
hub/helpers/peak_loads.py
Normal file
71
hub/helpers/peak_loads.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
import math
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.peak_calculation.loads_calculation import LoadsCalculation
|
||||
|
||||
_MONTH_STARTING_HOUR = [0, 744, 1416, 2160, 2880, 3624, 4344, 5088, 5832, 6552, 7296, 8016, math.inf]
|
||||
|
||||
def peak_loads_from_hourly(hourly_values):
|
||||
month = 1
|
||||
peaks = [0 for _ in range(12)]
|
||||
for i, value in enumerate(hourly_values):
|
||||
if _MONTH_STARTING_HOUR[month] <= i:
|
||||
month += 1
|
||||
if value > peaks[month-1]:
|
||||
peaks[month-1] = value
|
||||
return peaks
|
||||
|
||||
def heating_peak_loads_from_methodology(building):
|
||||
monthly_heating_loads = []
|
||||
ambient_temperature = building.external_temperature[cte.HOUR]['epw']
|
||||
for month in range(0, 12):
|
||||
ground_temperature = building.ground_temperature[cte.MONTH]['2'][month]
|
||||
heating_ambient_temperature = 100
|
||||
start_hour = _MONTH_STARTING_HOUR[month]
|
||||
end_hour = 8760
|
||||
if month < 11:
|
||||
end_hour = _MONTH_STARTING_HOUR[month + 1]
|
||||
for hour in range(start_hour, end_hour):
|
||||
temperature = ambient_temperature[hour]
|
||||
if temperature < heating_ambient_temperature:
|
||||
heating_ambient_temperature = temperature
|
||||
loads = LoadsCalculation(building)
|
||||
heating_load_transmitted = loads.get_heating_transmitted_load(heating_ambient_temperature, ground_temperature)
|
||||
heating_load_ventilation_sensible = loads.get_heating_ventilation_load_sensible(heating_ambient_temperature)
|
||||
heating_load_ventilation_latent = 0
|
||||
heating_load = heating_load_transmitted + heating_load_ventilation_sensible + heating_load_ventilation_latent
|
||||
if heating_load < 0:
|
||||
heating_load = 0
|
||||
monthly_heating_loads.append(heating_load)
|
||||
return monthly_heating_loads
|
||||
|
||||
def cooling_peak_loads_from_methodology(building):
|
||||
monthly_cooling_loads = []
|
||||
ambient_temperature = building.external_temperature[cte.HOUR]['epw']
|
||||
for month in range(0, 12):
|
||||
ground_temperature = building.ground_temperature[cte.MONTH]['2'][month]
|
||||
cooling_ambient_temperature = -100
|
||||
cooling_calculation_hour = -1
|
||||
start_hour = _MONTH_STARTING_HOUR[month]
|
||||
end_hour = 8760
|
||||
if month < 11:
|
||||
end_hour = _MONTH_STARTING_HOUR[month + 1]
|
||||
for hour in range(start_hour, end_hour):
|
||||
temperature = ambient_temperature[hour]
|
||||
if temperature > cooling_ambient_temperature:
|
||||
cooling_ambient_temperature = temperature
|
||||
cooling_calculation_hour = hour
|
||||
loads = LoadsCalculation(building)
|
||||
cooling_load_transmitted = loads.get_cooling_transmitted_load(cooling_ambient_temperature, ground_temperature)
|
||||
cooling_load_renovation_sensible = loads.get_cooling_ventilation_load_sensible(cooling_ambient_temperature)
|
||||
cooling_load_internal_gains_sensible = loads.get_internal_load_sensible()
|
||||
cooling_load_radiation = loads.get_radiation_load('sra', cooling_calculation_hour)
|
||||
cooling_load_sensible = cooling_load_transmitted + cooling_load_renovation_sensible - cooling_load_radiation \
|
||||
- cooling_load_internal_gains_sensible
|
||||
|
||||
cooling_load_latent = 0
|
||||
cooling_load = cooling_load_sensible + cooling_load_latent
|
||||
if cooling_load > 0:
|
||||
cooling_load = 0
|
||||
monthly_cooling_loads.append(abs(cooling_load))
|
||||
return monthly_cooling_loads
|
|
@ -4,7 +4,6 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
import datetime
|
||||
import math
|
||||
import sys
|
||||
from hub.hub_logger import get_logger
|
||||
|
@ -25,6 +24,7 @@ class NrcanPhysicsParameters:
|
|||
NrcanPhysicsParameters class
|
||||
"""
|
||||
def __init__(self, city, base_path, divide_in_storeys=False):
|
||||
# create a thread pool with 8 threads
|
||||
self._city = city
|
||||
self._path = base_path
|
||||
self._divide_in_storeys = divide_in_storeys
|
||||
|
@ -37,9 +37,8 @@ class NrcanPhysicsParameters:
|
|||
city = self._city
|
||||
nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog
|
||||
for building in city.buildings:
|
||||
function = Dictionaries().hub_function_to_nrcan_construction_function[building.function]
|
||||
try:
|
||||
function = Dictionaries().hub_function_to_nrcan_construction_function[building.function]
|
||||
|
||||
archetype = self._search_archetype(nrcan_catalog, function, building.year_of_construction, self._climate_zone)
|
||||
|
||||
except KeyError:
|
||||
|
@ -69,6 +68,7 @@ class NrcanPhysicsParameters:
|
|||
for internal_zone in building.internal_zones:
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
thermal_zone.total_floor_area = thermal_zone.footprint_area
|
||||
|
||||
for internal_zone in building.internal_zones:
|
||||
self._assign_values(internal_zone.thermal_zones, archetype)
|
||||
for thermal_zone in internal_zone.thermal_zones:
|
||||
|
|
|
@ -29,6 +29,7 @@ class Geojson:
|
|||
|
||||
def __init__(self,
|
||||
path,
|
||||
name_field=None,
|
||||
extrusion_height_field=None,
|
||||
year_of_construction_field=None,
|
||||
function_field=None,
|
||||
|
@ -41,6 +42,7 @@ class Geojson:
|
|||
self._max_y = cte.MIN_FLOAT
|
||||
self._max_z = 0
|
||||
self._city = None
|
||||
self._name_field = name_field
|
||||
self._extrusion_height_field = extrusion_height_field
|
||||
self._year_of_construction_field = year_of_construction_field
|
||||
self._function_field = function_field
|
||||
|
@ -58,80 +60,6 @@ class Geojson:
|
|||
if y < self._min_y:
|
||||
self._min_y = y
|
||||
|
||||
@staticmethod
|
||||
def _create_buildings_lod0(name, year_of_construction, function, surfaces_coordinates):
|
||||
surfaces = []
|
||||
buildings = []
|
||||
for zone, surface_coordinates in enumerate(surfaces_coordinates):
|
||||
points = igh.points_from_string(igh.remove_last_point_from_string(surface_coordinates))
|
||||
# geojson provides the roofs, need to be transform into grounds
|
||||
points = igh.invert_points(points)
|
||||
polygon = Polygon(points)
|
||||
polygon.area = igh.ground_area(points)
|
||||
surface = Surface(polygon, polygon)
|
||||
surfaces.append(surface)
|
||||
buildings.append(Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function))
|
||||
return buildings
|
||||
|
||||
@staticmethod
|
||||
def _create_buildings_lod1(name, year_of_construction, function, height, surface_coordinates):
|
||||
lod0_buildings = Geojson._create_buildings_lod0(name, year_of_construction, function, surface_coordinates)
|
||||
surfaces = []
|
||||
buildings = []
|
||||
|
||||
for zone, lod0_building in enumerate(lod0_buildings):
|
||||
for surface in lod0_building.grounds:
|
||||
|
||||
volume = surface.solid_polygon.area * height
|
||||
surfaces.append(surface)
|
||||
roof_coordinates = []
|
||||
# adding a roof means invert the polygon coordinates and change the Z value
|
||||
for coordinate in surface.solid_polygon.coordinates:
|
||||
roof_coordinate = np.array([coordinate[0], coordinate[1], height])
|
||||
# insert the roof rotated already
|
||||
roof_coordinates.insert(0, roof_coordinate)
|
||||
polygon = Polygon(roof_coordinates)
|
||||
polygon.area = surface.solid_polygon.area
|
||||
roof = Surface(polygon, polygon)
|
||||
surfaces.append(roof)
|
||||
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0
|
||||
coordinates_length = len(roof.solid_polygon.coordinates)
|
||||
for i, coordinate in enumerate(roof.solid_polygon.coordinates):
|
||||
j = i + 1
|
||||
if j == coordinates_length:
|
||||
j = 0
|
||||
next_coordinate = roof.solid_polygon.coordinates[j]
|
||||
wall_coordinates = [
|
||||
np.array([coordinate[0], coordinate[1], 0.0]),
|
||||
np.array([next_coordinate[0], next_coordinate[1], 0.0]),
|
||||
np.array([next_coordinate[0], next_coordinate[1], next_coordinate[2]]),
|
||||
np.array([coordinate[0], coordinate[1], coordinate[2]])
|
||||
]
|
||||
polygon = Polygon(wall_coordinates)
|
||||
wall = Surface(polygon, polygon)
|
||||
surfaces.append(wall)
|
||||
|
||||
building = Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function)
|
||||
building.volume = volume
|
||||
buildings.append(building)
|
||||
|
||||
return buildings
|
||||
|
||||
def _get_polygons(self, polygons, coordinates):
|
||||
if type(coordinates[0][self.X]) != float:
|
||||
polygons = []
|
||||
for element in coordinates:
|
||||
polygons = self._get_polygons(polygons, element)
|
||||
return polygons
|
||||
else:
|
||||
transformed_coordinates = ''
|
||||
for coordinate in coordinates:
|
||||
transformed = self._transformer.transform(coordinate[self.Y], coordinate[self.X])
|
||||
self._save_bounds(transformed[self.X], transformed[self.Y])
|
||||
transformed_coordinates = f'{transformed_coordinates} {transformed[self.X]} {transformed[self.Y]} 0.0'
|
||||
polygons.append(transformed_coordinates.lstrip(' '))
|
||||
return polygons
|
||||
|
||||
@staticmethod
|
||||
def _find_wall(line_1, line_2):
|
||||
for i in range(0, 2):
|
||||
|
@ -157,7 +85,7 @@ class Geojson:
|
|||
if point[2] < 0.5:
|
||||
ground_line.append(point)
|
||||
for entry in building_mapped:
|
||||
if building_mapped[entry]['shared_points'] <= 3:
|
||||
if building_mapped[entry]['shared_points'] <= 2:
|
||||
continue
|
||||
line = [building_mapped[entry]['line_start'], building_mapped[entry]['line_end']]
|
||||
neighbour_line = [building_mapped[entry]['neighbour_line_start'],
|
||||
|
@ -181,14 +109,13 @@ class Geojson:
|
|||
Get city out of a Geojson file
|
||||
"""
|
||||
if self._city is None:
|
||||
missing_functions = []
|
||||
buildings = []
|
||||
building_id = 0
|
||||
lod = 1
|
||||
lod = 0
|
||||
for feature in self._geojson['features']:
|
||||
extrusion_height = 0
|
||||
if self._extrusion_height_field is not None:
|
||||
extrusion_height = float(feature['properties'][self._extrusion_height_field])
|
||||
lod = 0.5
|
||||
year_of_construction = None
|
||||
if self._year_of_construction_field is not None:
|
||||
year_of_construction = int(feature['properties'][self._year_of_construction_field])
|
||||
|
@ -199,44 +126,186 @@ class Geojson:
|
|||
# use the transformation dictionary to retrieve the proper function
|
||||
if function in self._function_to_hub:
|
||||
function = self._function_to_hub[function]
|
||||
else:
|
||||
if function not in missing_functions:
|
||||
missing_functions.append(function)
|
||||
function = function
|
||||
geometry = feature['geometry']
|
||||
building_name = ''
|
||||
if 'id' in feature:
|
||||
building_name = feature['id']
|
||||
else:
|
||||
building_name = f'building_{building_id}'
|
||||
building_id += 1
|
||||
polygons = []
|
||||
for part, coordinates in enumerate(geometry['coordinates']):
|
||||
polygons = self._get_polygons(polygons, coordinates)
|
||||
for zone, polygon in enumerate(polygons):
|
||||
if extrusion_height == 0:
|
||||
buildings = buildings + Geojson._create_buildings_lod0(f'{building_name}_part_{part}',
|
||||
year_of_construction,
|
||||
function,
|
||||
[polygon])
|
||||
lod = 0
|
||||
else:
|
||||
if self._max_z < extrusion_height:
|
||||
self._max_z = extrusion_height
|
||||
buildings = buildings + Geojson._create_buildings_lod1(f'{building_name}_part_{part}',
|
||||
year_of_construction,
|
||||
function,
|
||||
extrusion_height,
|
||||
[polygon])
|
||||
if self._name_field is not None:
|
||||
building_name = feature['properties'][self._name_field]
|
||||
|
||||
if str(geometry['type']).lower() == 'polygon':
|
||||
buildings.append(self._parse_polygon(geometry['coordinates'],
|
||||
building_name,
|
||||
function,
|
||||
year_of_construction,
|
||||
extrusion_height))
|
||||
|
||||
elif str(geometry['type']).lower() == 'multipolygon':
|
||||
buildings.append(self._parse_multi_polygon(geometry['coordinates'],
|
||||
building_name,
|
||||
function,
|
||||
year_of_construction,
|
||||
extrusion_height))
|
||||
else:
|
||||
raise NotImplementedError(f'Geojson geometry type [{geometry["type"]}] unknown')
|
||||
self._city = City([self._min_x, self._min_y, 0.0], [self._max_x, self._max_y, self._max_z], 'epsg:26911')
|
||||
for building in buildings:
|
||||
# Do not include "small building-like structures" to buildings
|
||||
if building.floor_area >= 25:
|
||||
self._city.add_city_object(building)
|
||||
self._city.level_of_detail.geometry = lod
|
||||
if lod == 1:
|
||||
if lod > 0:
|
||||
lines_information = GeometryHelper.city_mapping(self._city, plot=False)
|
||||
self._store_shared_percentage_to_walls(self._city, lines_information)
|
||||
if len(missing_functions) > 0:
|
||||
print(f'There are unknown functions {missing_functions}')
|
||||
|
||||
return self._city
|
||||
|
||||
def _polygon_coordinates_to_3d(self, polygon_coordinates):
|
||||
transformed_coordinates = ''
|
||||
for coordinate in polygon_coordinates:
|
||||
transformed = self._transformer.transform(coordinate[self.Y], coordinate[self.X])
|
||||
self._save_bounds(transformed[self.X], transformed[self.Y])
|
||||
transformed_coordinates = f'{transformed_coordinates} {transformed[self.X]} {transformed[self.Y]} 0.0'
|
||||
return transformed_coordinates.lstrip(' ')
|
||||
|
||||
def _parse_polygon(self, coordinates, building_name, function, year_of_construction, extrusion_height):
|
||||
surfaces = []
|
||||
for polygon_coordinates in coordinates:
|
||||
points = igh.points_from_string(
|
||||
igh.remove_last_point_from_string(
|
||||
self._polygon_coordinates_to_3d(polygon_coordinates)
|
||||
)
|
||||
)
|
||||
points = igh.invert_points(points)
|
||||
polygon = Polygon(points)
|
||||
polygon.area = igh.ground_area(points)
|
||||
surface = Surface(polygon, polygon)
|
||||
if surface.type == cte.GROUND:
|
||||
surfaces.append(surface)
|
||||
else:
|
||||
distance = cte.MAX_FLOAT
|
||||
hole_connect = 0
|
||||
surface_connect = 0
|
||||
for hole_index, hole_coordinate in enumerate(polygon.coordinates):
|
||||
for surface_index, ground_coordinate in enumerate(surfaces[-1].solid_polygon.coordinates):
|
||||
current_distance = GeometryHelper.distance_between_points(hole_coordinate, ground_coordinate)
|
||||
if current_distance < distance:
|
||||
distance = current_distance
|
||||
hole_connect = hole_index
|
||||
surface_connect = surface_index
|
||||
|
||||
hole = polygon.coordinates[hole_connect:] + polygon.coordinates[:hole_connect] + [polygon.coordinates[hole_connect]]
|
||||
prefix_coordinates = surfaces[-1].solid_polygon.coordinates[:surface_connect+1]
|
||||
trail_coordinates = surfaces[-1].solid_polygon.coordinates[surface_connect:]
|
||||
coordinates = prefix_coordinates + hole + trail_coordinates
|
||||
polygon = Polygon(coordinates)
|
||||
polygon.area = igh.ground_area(coordinates)
|
||||
surfaces[-1] = Surface(polygon, polygon)
|
||||
if len(surfaces) > 1:
|
||||
raise ValueError('too many surfaces!!!!')
|
||||
building = Building(f'{building_name}', surfaces, year_of_construction, function)
|
||||
if extrusion_height == 0:
|
||||
return building
|
||||
else:
|
||||
volume = 0
|
||||
for ground in building.grounds:
|
||||
volume += ground.solid_polygon.area * extrusion_height
|
||||
roof_coordinates = []
|
||||
# adding a roof means invert the polygon coordinates and change the Z value
|
||||
for coordinate in ground.solid_polygon.coordinates:
|
||||
roof_coordinate = np.array([coordinate[0], coordinate[1], extrusion_height])
|
||||
# insert the roof rotated already
|
||||
roof_coordinates.insert(0, roof_coordinate)
|
||||
roof_polygon = Polygon(roof_coordinates)
|
||||
roof_polygon.area = ground.solid_polygon.area
|
||||
roof = Surface(roof_polygon, roof_polygon)
|
||||
surfaces.append(roof)
|
||||
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0
|
||||
coordinates_length = len(roof.solid_polygon.coordinates)
|
||||
for i, coordinate in enumerate(roof.solid_polygon.coordinates):
|
||||
j = i + 1
|
||||
if j == coordinates_length:
|
||||
j = 0
|
||||
next_coordinate = roof.solid_polygon.coordinates[j]
|
||||
wall_coordinates = [
|
||||
np.array([coordinate[0], coordinate[1], 0.0]),
|
||||
np.array([next_coordinate[0], next_coordinate[1], 0.0]),
|
||||
np.array([next_coordinate[0], next_coordinate[1], next_coordinate[2]]),
|
||||
np.array([coordinate[0], coordinate[1], coordinate[2]])
|
||||
]
|
||||
polygon = Polygon(wall_coordinates)
|
||||
wall = Surface(polygon, polygon)
|
||||
surfaces.append(wall)
|
||||
building = Building(f'{building_name}', surfaces, year_of_construction, function)
|
||||
building.volume = volume
|
||||
return building
|
||||
|
||||
def _parse_multi_polygon(self, polygons_coordinates, building_name, function, year_of_construction, extrusion_height):
|
||||
surfaces = []
|
||||
for coordinates in polygons_coordinates:
|
||||
for polygon_coordinates in coordinates:
|
||||
points = igh.points_from_string(
|
||||
igh.remove_last_point_from_string(
|
||||
self._polygon_coordinates_to_3d(polygon_coordinates)
|
||||
)
|
||||
)
|
||||
points = igh.invert_points(points)
|
||||
polygon = Polygon(points)
|
||||
polygon.area = igh.ground_area(points)
|
||||
surface = Surface(polygon, polygon)
|
||||
if surface.type == cte.GROUND:
|
||||
surfaces.append(surface)
|
||||
else:
|
||||
distance = cte.MAX_FLOAT
|
||||
hole_connect = 0
|
||||
surface_connect = 0
|
||||
for hole_index, hole_coordinate in enumerate(polygon.coordinates):
|
||||
for surface_index, ground_coordinate in enumerate(surfaces[-1].solid_polygon.coordinates):
|
||||
current_distance = GeometryHelper.distance_between_points(hole_coordinate, ground_coordinate)
|
||||
if current_distance < distance:
|
||||
distance = current_distance
|
||||
hole_connect = hole_index
|
||||
surface_connect = surface_index
|
||||
hole = polygon.coordinates[hole_connect:] + polygon.coordinates[:hole_connect]
|
||||
prefix_coordinates = surfaces[-1].solid_polygon.coordinates[:surface_connect]
|
||||
trail_coordinates = surfaces[-1].solid_polygon.coordinates[surface_connect:]
|
||||
coordinates = prefix_coordinates + hole + [hole[0]] + trail_coordinates
|
||||
polygon = Polygon(coordinates)
|
||||
polygon.area = igh.ground_area(coordinates)
|
||||
surfaces[-1] = Surface(polygon, polygon)
|
||||
building = Building(f'{building_name}', surfaces, year_of_construction, function)
|
||||
if extrusion_height == 0:
|
||||
return building
|
||||
else:
|
||||
volume = 0
|
||||
for ground in building.grounds:
|
||||
volume += ground.solid_polygon.area * extrusion_height
|
||||
roof_coordinates = []
|
||||
# adding a roof means invert the polygon coordinates and change the Z value
|
||||
for coordinate in ground.solid_polygon.coordinates:
|
||||
roof_coordinate = np.array([coordinate[0], coordinate[1], extrusion_height])
|
||||
# insert the roof rotated already
|
||||
roof_coordinates.insert(0, roof_coordinate)
|
||||
roof_polygon = Polygon(roof_coordinates)
|
||||
roof_polygon.area = ground.solid_polygon.area
|
||||
roof = Surface(roof_polygon, roof_polygon)
|
||||
surfaces.append(roof)
|
||||
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0
|
||||
coordinates_length = len(roof.solid_polygon.coordinates)
|
||||
for i, coordinate in enumerate(roof.solid_polygon.coordinates):
|
||||
j = i + 1
|
||||
if j == coordinates_length:
|
||||
j = 0
|
||||
next_coordinate = roof.solid_polygon.coordinates[j]
|
||||
wall_coordinates = [
|
||||
np.array([coordinate[0], coordinate[1], 0.0]),
|
||||
np.array([next_coordinate[0], next_coordinate[1], 0.0]),
|
||||
np.array([next_coordinate[0], next_coordinate[1], next_coordinate[2]]),
|
||||
np.array([coordinate[0], coordinate[1], coordinate[2]])
|
||||
]
|
||||
polygon = Polygon(wall_coordinates)
|
||||
wall = Surface(polygon, polygon)
|
||||
surfaces.append(wall)
|
||||
building = Building(f'{building_name}', surfaces, year_of_construction, function)
|
||||
building.volume = volume
|
||||
return building
|
||||
|
|
|
@ -25,6 +25,7 @@ class GeometryFactory:
|
|||
def __init__(self, file_type,
|
||||
path=None,
|
||||
data_frame=None,
|
||||
name_field=None,
|
||||
height_field=None,
|
||||
year_of_construction_field=None,
|
||||
function_field=None,
|
||||
|
@ -37,6 +38,7 @@ class GeometryFactory:
|
|||
raise Exception(err_msg)
|
||||
self._path = path
|
||||
self._data_frame = data_frame
|
||||
self._name_field = name_field
|
||||
self._height_field = height_field
|
||||
self._year_of_construction_field = year_of_construction_field
|
||||
self._function_field = function_field
|
||||
|
@ -79,6 +81,7 @@ class GeometryFactory:
|
|||
:return: City
|
||||
"""
|
||||
return Geojson(self._path,
|
||||
self._name_field,
|
||||
self._height_field,
|
||||
self._year_of_construction_field,
|
||||
self._function_field,
|
||||
|
@ -106,6 +109,9 @@ class GeometryFactory:
|
|||
Enrich the city given to the class using the class given handler
|
||||
:return: City
|
||||
"""
|
||||
if self._data_frame is None:
|
||||
self._data_frame = geopandas.read_file(self._path)
|
||||
return GPandas(self._data_frame).city
|
||||
return Geojson(self._path,
|
||||
self._name_field,
|
||||
self._height_field,
|
||||
self._year_of_construction_field,
|
||||
self._function_field,
|
||||
self._function_to_hub).city
|
||||
|
|
|
@ -4,7 +4,6 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guillermo.GutierrezMorote@concordia.ca
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import pandas as pd
|
||||
import csv
|
||||
|
@ -13,7 +12,7 @@ import hub.helpers.constants as cte
|
|||
|
||||
class InselMonthlyEnergyBalance:
|
||||
"""
|
||||
Import SRA results
|
||||
Import insel monthly energy balance results
|
||||
"""
|
||||
def __init__(self, city, base_path):
|
||||
|
||||
|
@ -40,60 +39,55 @@ class InselMonthlyEnergyBalance:
|
|||
monthly_cooling = pd.DataFrame(cooling, columns=[cte.INSEL_MEB]).astype(float)
|
||||
return monthly_heating, monthly_cooling
|
||||
|
||||
def _dhw_demand(self):
|
||||
def _dhw_and_electric_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:
|
||||
domestic_hot_water_demand = [0] * 12
|
||||
lighting_demand = [0] * 12
|
||||
appliances_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']
|
||||
peak_flow = thermal_zone.domestic_hot_water.peak_flow
|
||||
service_temperature = thermal_zone.domestic_hot_water.service_temperature
|
||||
lighting_density = thermal_zone.lighting.density
|
||||
appliances_density = thermal_zone.appliances.density
|
||||
|
||||
for month in range(0, 12):
|
||||
total_dhw_demand = 0
|
||||
total_lighting = 0
|
||||
total_appliances = 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
|
||||
total_lighting += total_day * cte.DAYS_A_MONTH[day_type][month] * 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
|
||||
total_appliances += total_day * cte.DAYS_A_MONTH[day_type][month] * appliances_density
|
||||
appliances_demand.append(total_appliances * area)
|
||||
|
||||
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 = peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY * (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])
|
||||
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])
|
||||
|
||||
|
@ -109,5 +103,4 @@ class InselMonthlyEnergyBalance:
|
|||
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()
|
||||
self._dhw_and_electric_demand()
|
||||
|
|
|
@ -55,7 +55,7 @@ class ResultFactory:
|
|||
"""
|
||||
InselHeatPumpEnergyDemand(self._city, self._base_path, self._hp_model).enrich()
|
||||
|
||||
def _insel_meb(self):
|
||||
def _insel_monthly_energy_balance(self):
|
||||
"""
|
||||
Enrich the city with insel monthly energy balance results
|
||||
"""
|
||||
|
|
|
@ -47,12 +47,12 @@ class NrcanUsageParameters:
|
|||
sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
|
||||
continue
|
||||
|
||||
usage_name = Dictionaries().hub_usage_to_comnet_usage[building.function]
|
||||
comnet_usage_name = Dictionaries().hub_usage_to_comnet_usage[building.function]
|
||||
try:
|
||||
comnet_archetype_usage = self._search_archetypes(comnet_catalog, usage_name)
|
||||
comnet_archetype_usage = self._search_archetypes(comnet_catalog, comnet_usage_name)
|
||||
except KeyError:
|
||||
logger.error(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
|
||||
sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
|
||||
logger.error(f'Building {building.name} has unknown usage archetype for usage: {comnet_usage_name}\n')
|
||||
sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {comnet_usage_name}\n')
|
||||
continue
|
||||
|
||||
for internal_zone in building.internal_zones:
|
||||
|
@ -83,8 +83,10 @@ class NrcanUsageParameters:
|
|||
@staticmethod
|
||||
def _assign_values(usage, archetype, volume_per_area, cold_water_temperature):
|
||||
if archetype.mechanical_air_change > 0:
|
||||
# ACH
|
||||
usage.mechanical_air_change = archetype.mechanical_air_change
|
||||
elif archetype.ventilation_rate > 0:
|
||||
# m3/m2.s to ACH
|
||||
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area * cte.HOUR_TO_SECONDS
|
||||
else:
|
||||
usage.mechanical_air_change = 0
|
||||
|
|
|
@ -71,7 +71,6 @@ class EpwWeatherParameters:
|
|||
except SystemExit:
|
||||
sys.stderr.write(f'Error: wrong formatting of weather file {self._path}\n')
|
||||
sys.exit()
|
||||
|
||||
for building in self._city.buildings:
|
||||
building.ground_temperature[cte.MONTH] = ground_temperature
|
||||
ground_temperature = {}
|
||||
|
|
|
@ -54,3 +54,7 @@ class WeatherFactory:
|
|||
:return: None
|
||||
"""
|
||||
getattr(self, self._handler, lambda: None)()
|
||||
|
||||
def enrich_debug(self):
|
||||
_path = Path(self._base_path / 'epw').resolve()
|
||||
return EpwWeatherParameters(self._city, _path, self._file_name)
|
||||
|
|
|
@ -64,15 +64,8 @@ class CityLayerTest(TestCase):
|
|||
city = GeometryFactory('gpandas', data_frame=buildings_df).city
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
EnergyBuildingsExportsFactory('idf', city, output_path, target_buildings=target_buildings,
|
||||
adjacent_buildings=adjacent_buildings).export_debug()
|
||||
EnergyBuildingsExportsFactory('idf', city, output_path, target_buildings=target_buildings).export_debug()
|
||||
filepath = os.path.join(output_path, city.name + ".idf")
|
||||
newfilepath = filepath[:-4] + "_" + uuid.uuid4().hex[:10] + ".idf"
|
||||
os.rename(filepath, newfilepath)
|
||||
return newfilepath
|
||||
|
||||
def test_city_layers(self):
|
||||
json_path = str((Path(__file__).parent / 'tests_data' / 'city_layers.json').resolve())
|
||||
with open(json_path) as json_file:
|
||||
data = json.loads(json_file.read())
|
||||
self._genidf(data)
|
||||
|
|
|
@ -27,13 +27,7 @@ class TestCityMerge(TestCase):
|
|||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
self._weather_file = (self._example_path / 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
|
||||
self._climate_file = (self._example_path / 'New_York.cli').resolve()
|
||||
self._executable = None
|
||||
if platform.system() == 'Linux':
|
||||
self._executable = 'citysim_sra'
|
||||
if platform.system() == 'Darwin':
|
||||
self._executable = 'citysim_sra'
|
||||
elif platform.system() == 'Windows':
|
||||
self._executable = 'shortwave_integer'
|
||||
self._executable = 'sra'
|
||||
|
||||
def _get_citygml(self, file):
|
||||
file_path = (self._example_path / file).resolve()
|
||||
|
|
|
@ -18,11 +18,13 @@ class TestCostsCatalog(TestCase):
|
|||
self.assertIsNotNone(catalog, 'catalog is none')
|
||||
content = catalog.entries()
|
||||
self.assertTrue(len(content.archetypes) == 2)
|
||||
print(catalog)
|
||||
|
||||
# retrieving all the entries should not raise any exceptions
|
||||
for category in catalog_categories:
|
||||
for value in catalog_categories[category]:
|
||||
catalog.get_entry(value)
|
||||
print(value)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
catalog.get_entry('unknown')
|
||||
|
|
|
@ -13,6 +13,7 @@ from hub.imports.geometry_factory import GeometryFactory
|
|||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
import hub.helpers.constants as cte
|
||||
|
@ -89,7 +90,6 @@ class TestExports(TestCase):
|
|||
"""
|
||||
self._export_building_energy('energy_ade')
|
||||
|
||||
|
||||
def test_sra_export(self):
|
||||
"""
|
||||
export to SRA
|
||||
|
@ -110,6 +110,7 @@ class TestExports(TestCase):
|
|||
ConstructionFactory('nrcan', city).enrich()
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
WeatherFactory('epw', city, file_name='CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').enrich()
|
||||
try:
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
except Exception:
|
||||
|
|
|
@ -8,7 +8,10 @@ from pathlib import Path
|
|||
from unittest import TestCase
|
||||
|
||||
import hub.exports.exports_factory
|
||||
from hub.helpers.dictionaries import MontrealFunctionToHubFunction
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.helpers.dictionaries import MontrealFunctionToHubFunction, Dictionaries
|
||||
from hub.helpers.geometry_helper import GeometryHelper
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
|
@ -134,39 +137,44 @@ class TestGeometryFactory(TestCase):
|
|||
"""
|
||||
Test geojson import
|
||||
"""
|
||||
file = '2000_buildings.geojson'
|
||||
file = Path(self._example_path / '2000_buildings.geojson').resolve()
|
||||
city = GeometryFactory('geojson',
|
||||
path=(self._example_path / file).resolve(),
|
||||
path=file,
|
||||
height_field='building_height',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
name_field='ID_UEV',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=MontrealFunctionToHubFunction().dictionary).city
|
||||
# include 25 square meter condition for a building reduces buildings number from 2289 to 2057
|
||||
self.assertEqual(2057, len(city.buildings), 'wrong number of buildings')
|
||||
hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export()
|
||||
self.assertEqual(1964, len(city.buildings), 'wrong number of buildings')
|
||||
|
||||
def test_map_neighbours(self):
|
||||
"""
|
||||
Test neighbours map creation
|
||||
"""
|
||||
file = 'neighbours.geojson'
|
||||
|
||||
city = self._get_city(file, 'geojson',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='LIBELLE_UT')
|
||||
info_lod0 = GeometryHelper.city_mapping(city, plot=False)
|
||||
city = self._get_city(file, 'geojson',
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='LIBELLE_UT')
|
||||
info_lod1 = GeometryHelper.city_mapping(city, plot=False)
|
||||
city = self._get_city(file, 'geojson',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='LIBELLE_UT')
|
||||
|
||||
info_lod0 = GeometryHelper.city_mapping(city, plot=False)
|
||||
hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export()
|
||||
self.assertEqual(info_lod0, info_lod1)
|
||||
for building in city.buildings:
|
||||
self.assertEqual(2, len(building.neighbours))
|
||||
|
||||
self.assertEqual('2_part_0_zone_0', city.city_object('1_part_0_zone_0').neighbours[0].name)
|
||||
self.assertEqual('3_part_0_zone_0', city.city_object('1_part_0_zone_0').neighbours[1].name)
|
||||
self.assertEqual('1_part_0_zone_0', city.city_object('2_part_0_zone_0').neighbours[0].name)
|
||||
self.assertEqual('3_part_0_zone_0', city.city_object('2_part_0_zone_0').neighbours[1].name)
|
||||
self.assertEqual('1_part_0_zone_0', city.city_object('3_part_0_zone_0').neighbours[0].name)
|
||||
self.assertEqual('2_part_0_zone_0', city.city_object('3_part_0_zone_0').neighbours[1].name)
|
||||
self.assertEqual('2', city.city_object('1').neighbours[0].name)
|
||||
self.assertEqual('3', city.city_object('1').neighbours[1].name)
|
||||
self.assertEqual('1', city.city_object('2').neighbours[0].name)
|
||||
self.assertEqual('3', city.city_object('2').neighbours[1].name)
|
||||
self.assertEqual('1', city.city_object('3').neighbours[0].name)
|
||||
self.assertEqual('2', city.city_object('3').neighbours[1].name)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ from unittest import TestCase
|
|||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.city_model_structure.greenery.vegetation import Vegetation
|
||||
from hub.city_model_structure.greenery.soil import Soil
|
||||
|
@ -21,9 +22,7 @@ class GreeneryInIdf(TestCase):
|
|||
"""
|
||||
GreeneryInIdf TestCase 1
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def test_greenery_in_idf():
|
||||
def test_greenery_in_idf(self):
|
||||
city_file = "tests_data/one_building_in_kelowna.gml"
|
||||
output_path = Path('tests_outputs/').resolve()
|
||||
|
||||
|
@ -32,6 +31,7 @@ class GreeneryInIdf(TestCase):
|
|||
building.year_of_construction = 2006
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
WeatherFactory('epw', city, file_name='CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').enrich()
|
||||
vegetation_name = 'BaseEco'
|
||||
soil_thickness = 0.18
|
||||
soil_name = 'EcoRoofSoil'
|
||||
|
@ -66,36 +66,14 @@ class GreeneryInIdf(TestCase):
|
|||
if surface.type == cte.ROOF:
|
||||
surface.vegetation = vegetation
|
||||
|
||||
_idf_2 = EnergyBuildingsExportsFactory('idf', city, output_path).export_debug()
|
||||
_idf_2.run()
|
||||
with open((output_path / f'{city.name}_out.csv').resolve()) as f:
|
||||
reader = csv.reader(f, delimiter=',')
|
||||
heating = 0
|
||||
cooling = 0
|
||||
for row in reader:
|
||||
if '00:00' in row[0]:
|
||||
heating += float(row[8]) / 3600000
|
||||
cooling += float(row[9]) / 3600000
|
||||
|
||||
print('With greenery')
|
||||
print(f'heating: {heating} MWh/yr, cooling: {cooling} MWh/yr')
|
||||
|
||||
_idf = EnergyBuildingsExportsFactory('idf', city, output_path).export()
|
||||
self.assertIsNotNone(_idf)
|
||||
city = GeometryFactory('citygml', path=city_file).city
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = 2006
|
||||
ConstructionFactory('nrel', city).enrich()
|
||||
UsageFactory('comnet', city).enrich()
|
||||
WeatherFactory('epw', city, file_name='CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').enrich()
|
||||
_idf = EnergyBuildingsExportsFactory('idf', city, output_path).export()
|
||||
_idf.run()
|
||||
with open((output_path / f'{city.name}_out.csv').resolve()) as f:
|
||||
reader = csv.reader(f, delimiter=',')
|
||||
heating = 0
|
||||
cooling = 0
|
||||
for row in reader:
|
||||
if '00:00' in row[0]:
|
||||
heating += float(row[8]) / 3600000
|
||||
cooling += float(row[9]) / 3600000
|
||||
|
||||
print('Without greenery')
|
||||
print(f'heating: {heating} MWh/yr, cooling: {cooling} MWh/yr')
|
||||
self.assertIsNotNone(_idf)
|
||||
|
||||
|
|
115
hub/unittests/test_results_import.py
Normal file
115
hub/unittests/test_results_import.py
Normal file
|
@ -0,0 +1,115 @@
|
|||
"""
|
||||
TestExports test and validate the city export formats
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
import pandas as pd
|
||||
|
||||
import hub.helpers.constants as cte
|
||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
|
||||
|
||||
class TestResultsImport(TestCase):
|
||||
"""
|
||||
TestImports class contains the unittest for import functionality
|
||||
"""
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
self._example_path = (Path(__file__).parent / 'tests_data').resolve()
|
||||
self._gml_path = (self._example_path / 'FZK_Haus_LoD_2.gml').resolve()
|
||||
self._output_path = (Path(__file__).parent / 'tests_outputs').resolve()
|
||||
self._city = GeometryFactory('citygml',
|
||||
self._gml_path,
|
||||
function_to_hub=Dictionaries().alkis_function_to_hub_function).city
|
||||
ConstructionFactory('nrcan', self._city).enrich()
|
||||
UsageFactory('nrcan', self._city).enrich()
|
||||
|
||||
def test_sra_import(self):
|
||||
weather_file = (self._example_path / 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
|
||||
ExportsFactory('sra', self._city, self._output_path, weather_file=weather_file, weather_format='epw').export()
|
||||
sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', self._city, self._output_path).enrich()
|
||||
# Check that all the buildings have radiance in the surfaces
|
||||
for building in self._city.buildings:
|
||||
for surface in building.surfaces:
|
||||
self.assertIsNotNone(surface.global_irradiance)
|
||||
|
||||
def test_meb_import(self):
|
||||
weather_file = (self._example_path / 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
|
||||
ExportsFactory('sra', self._city, self._output_path, weather_file=weather_file, weather_format='epw').export()
|
||||
sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', self._city, self._output_path).enrich()
|
||||
EnergyBuildingsExportsFactory('insel_monthly_energy_balance', self._city, self._output_path).export()
|
||||
for building in self._city.buildings:
|
||||
insel_path = (self._output_path / f'{building.name}.insel')
|
||||
subprocess.run(['insel', str(insel_path)])
|
||||
ResultFactory('insel_monthly_energy_balance', self._city, self._output_path).enrich()
|
||||
# Check that all the buildings have heating and cooling values
|
||||
for building in self._city.buildings:
|
||||
self.assertIsNotNone(building.heating[cte.MONTH][cte.INSEL_MEB])
|
||||
self.assertIsNotNone(building.cooling[cte.MONTH][cte.INSEL_MEB])
|
||||
self.assertIsNotNone(building.heating[cte.YEAR][cte.INSEL_MEB])
|
||||
self.assertIsNotNone(building.cooling[cte.YEAR][cte.INSEL_MEB])
|
||||
|
||||
def test_peak_loads(self):
|
||||
# todo: this is not technically a import
|
||||
weather_file = (self._example_path / 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve()
|
||||
ExportsFactory('sra', self._city, self._output_path, weather_file=weather_file, weather_format='epw').export()
|
||||
sra_path = (self._output_path / f'{self._city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', self._city, self._output_path).enrich()
|
||||
for building in self._city.buildings:
|
||||
self.assertIsNotNone(building.heating_peak_load)
|
||||
self.assertIsNotNone(building.cooling_peak_load)
|
||||
|
||||
values = [0 for _ in range(8760)]
|
||||
values[0] = 1000
|
||||
expected_yearly = pd.DataFrame([1000], columns=['expected'])
|
||||
expected_monthly_list = [0 for _ in range(12)]
|
||||
expected_monthly_list[0] = 1000
|
||||
expected_monthly = pd.DataFrame(expected_monthly_list, columns=['expected'])
|
||||
for building in self._city.buildings:
|
||||
building.heating[cte.HOUR] = pd.DataFrame(values, columns=['dummy'])
|
||||
building.cooling[cte.HOUR] = pd.DataFrame(values, columns=['dummy'])
|
||||
self.assertIsNotNone(building.heating_peak_load)
|
||||
self.assertIsNotNone(building.cooling_peak_load)
|
||||
pd.testing.assert_series_equal(
|
||||
building.heating_peak_load[cte.YEAR]['heating peak loads'],
|
||||
expected_yearly['expected'],
|
||||
check_names=False
|
||||
)
|
||||
pd.testing.assert_series_equal(
|
||||
building.cooling_peak_load[cte.YEAR]['cooling peak loads'],
|
||||
expected_yearly['expected'],
|
||||
check_names=False
|
||||
)
|
||||
pd.testing.assert_series_equal(
|
||||
building.heating_peak_load[cte.MONTH]['heating peak loads'],
|
||||
expected_monthly['expected'],
|
||||
check_names=False
|
||||
)
|
||||
pd.testing.assert_series_equal(
|
||||
building.cooling_peak_load[cte.MONTH]['cooling peak loads'],
|
||||
expected_monthly['expected'],
|
||||
check_names=False
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
@ -133,11 +133,11 @@ class TestUsageFactory(TestCase):
|
|||
"""
|
||||
Enrich the city with the usage information from nrcan and verify it
|
||||
"""
|
||||
file = 'selected_building.geojson'
|
||||
file = 'concordia.geojson'
|
||||
file_path = (self._example_path / file).resolve()
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='building_height',
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,80 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Generated by: --><!-- IFC -> cityGML Converter --><!-- (C) - Institute for Applied Computer Science --><!-- Forschungszentrum Karlsruhe --><!-- Not for commercial use --><!-- Generated by: IfcExplorer--><!-- cityGML Schema: 1.0.0 --><!-- Level of Detail 1--><!-- Creation Date: Tuesday, 23 November 2010 - 10:37:59--><!-- Edited Manually in Oxygen 8.2 --><!-- Modified by GMLOffset.xslt at Mon Dec 6 2010 --><!-- Version 2 Building located in the area of KIT Campus North)--><!-- Modified by GMLOffset.xslt at Wed Dec 8 2010 --><!-- Modified by GMLOffset.xslt at Wed Mar 29 2017 --><core:CityModel xsi:schemaLocation="http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd" xmlns:core="http://www.opengis.net/citygml/2.0" xmlns="http://www.opengis.net/citygml/profiles/base/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:grp="http://www.opengis.net/citygml/cityobjectgroup/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<!-- Manually edited by KHH 23.01.2017, Address added, roof edge added -->
|
||||
<gml:name>AC14-FZK-Haus</gml:name>
|
||||
<gml:boundedBy>
|
||||
<gml:Envelope srsDimension="3" srsName="urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH">
|
||||
<gml:lowerCorner srsDimension="3">457842 5439083 111.8 </gml:lowerCorner>
|
||||
<gml:upperCorner srsDimension="3">457854 5439093 118.317669 </gml:upperCorner>
|
||||
</gml:Envelope>
|
||||
</gml:boundedBy>
|
||||
<core:cityObjectMember>
|
||||
<bldg:Building gml:id="UUID_d281adfc-4901-0f52-540b-4cc1a9325f82">
|
||||
<gml:description>FZK-Haus (Forschungszentrum Karlsruhe, now KIT), created by Karl-Heinz
|
||||
Haefele </gml:description>
|
||||
<gml:name>AC14-FZK-Haus</gml:name>
|
||||
<core:creationDate>2017-01-23</core:creationDate>
|
||||
<core:relativeToTerrain>entirelyAboveTerrain</core:relativeToTerrain>
|
||||
<gen:measureAttribute name="GrossPlannedArea">
|
||||
<gen:value uom="m2">120.00</gen:value>
|
||||
</gen:measureAttribute>
|
||||
<gen:stringAttribute name="ConstructionMethod">
|
||||
<gen:value>New Building</gen:value>
|
||||
</gen:stringAttribute>
|
||||
<gen:stringAttribute name="IsLandmarked">
|
||||
<gen:value>NO</gen:value>
|
||||
</gen:stringAttribute>
|
||||
<bldg:class codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_class.xml">1000</bldg:class>
|
||||
<bldg:function codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_function.xml">1000</bldg:function>
|
||||
<bldg:usage codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_usage.xml">1000</bldg:usage>
|
||||
<bldg:yearOfConstruction>2020</bldg:yearOfConstruction>
|
||||
<bldg:roofType codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_roofType.xml">1030</bldg:roofType>
|
||||
<bldg:measuredHeight uom="m">6.52</bldg:measuredHeight>
|
||||
<bldg:storeysAboveGround>2</bldg:storeysAboveGround>
|
||||
<bldg:storeysBelowGround>0</bldg:storeysBelowGround>
|
||||
<bldg:lod0FootPrint>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon>
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList srsDimension="3">457842 5439083 111.8 457842 5439093 111.8 457854 5439093 111.8 457854 5439083 111.8 457842 5439083 111.8 </gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod0FootPrint>
|
||||
<bldg:lod0RoofEdge>
|
||||
<gml:MultiSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon>
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList srsDimension="3">457841.5 5439082.5 111.8 457841.5 5439093.5 111.8 457854.5 5439093.5 111.8 457854.5 5439082.5 111.8 457841.5 5439082.5 111.8 </gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:MultiSurface>
|
||||
</bldg:lod0RoofEdge>
|
||||
<bldg:address>
|
||||
<core:Address>
|
||||
<core:xalAddress>
|
||||
<xAL:AddressDetails>
|
||||
<xAL:Locality Type="Town">
|
||||
<xAL:LocalityName>Eggenstein-Leopoldshafen</xAL:LocalityName>
|
||||
<xAL:Thoroughfare Type="Street">
|
||||
<xAL:ThoroughfareNumber>4711</xAL:ThoroughfareNumber>
|
||||
<xAL:ThoroughfareName>Spöcker Straße</xAL:ThoroughfareName>
|
||||
</xAL:Thoroughfare>
|
||||
<xAL:PostalCode>
|
||||
<xAL:PostalCodeNumber>76344</xAL:PostalCodeNumber>
|
||||
</xAL:PostalCode>
|
||||
</xAL:Locality>
|
||||
</xAL:AddressDetails>
|
||||
</core:xalAddress>
|
||||
</core:Address>
|
||||
</bldg:address>
|
||||
</bldg:Building>
|
||||
</core:cityObjectMember>
|
||||
</core:CityModel>
|
|
@ -1,116 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Generated by: --><!-- IFC -> cityGML Converter --><!-- (C) - Institute for Applied Computer Science --><!-- Forschungszentrum Karlsruhe --><!-- Not for commercial use --><!-- Generated by: IfcExplorer--><!-- cityGML Schema: 1.0.0 --><!-- Level of Detail 1--><!-- Creation Date: Tuesday, 23 November 2010 - 10:37:59--><!-- Edited Manually in Oxygen 8.2 --><!-- Modified by GMLOffset.xslt at Mon Dec 6 2010 --><!-- Version 2 Building located in the area of KIT Campus North)--><!-- Modified by GMLOffset.xslt at Wed Dec 8 2010 --><!-- Modified by GMLOffset.xslt at Wed Mar 29 2017 --><core:CityModel xsi:schemaLocation="http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd" xmlns:core="http://www.opengis.net/citygml/2.0" xmlns="http://www.opengis.net/citygml/profiles/base/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:grp="http://www.opengis.net/citygml/cityobjectgroup/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<!-- Manually edited by KHH 23.01.2017, CityGML 2.0, Address added, roof edge added -->
|
||||
<gml:name>AC14-FZK-Haus</gml:name>
|
||||
<gml:boundedBy>
|
||||
<gml:Envelope srsDimension="3" srsName="urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH">
|
||||
<gml:lowerCorner srsDimension="3">457842 5439083 111.8 </gml:lowerCorner>
|
||||
<gml:upperCorner srsDimension="3">457854 5439093 118.317669 </gml:upperCorner>
|
||||
</gml:Envelope>
|
||||
</gml:boundedBy>
|
||||
<core:cityObjectMember>
|
||||
<bldg:Building gml:id="UUID_d281adfc-4901-0f52-540b-4cc1a9325f82">
|
||||
<gml:description>FZK-Haus (Forschungszentrum Karlsruhe, now KIT), created by Karl-Heinz
|
||||
Haefele </gml:description>
|
||||
<gml:name>AC14-FZK-Haus</gml:name>
|
||||
<core:creationDate>2017-01-23</core:creationDate>
|
||||
<core:relativeToTerrain>entirelyAboveTerrain</core:relativeToTerrain>
|
||||
<gen:measureAttribute name="GrossPlannedArea">
|
||||
<gen:value uom="m2">120.00</gen:value>
|
||||
</gen:measureAttribute>
|
||||
<gen:stringAttribute name="ConstructionMethod">
|
||||
<gen:value>New Building</gen:value>
|
||||
</gen:stringAttribute>
|
||||
<gen:stringAttribute name="IsLandmarked">
|
||||
<gen:value>NO</gen:value>
|
||||
</gen:stringAttribute>
|
||||
<bldg:class codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_class.xml">1000</bldg:class>
|
||||
<bldg:function codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_function.xml">1000</bldg:function>
|
||||
<bldg:usage codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_usage.xml">1000</bldg:usage>
|
||||
<bldg:yearOfConstruction>2020</bldg:yearOfConstruction>
|
||||
<bldg:roofType codeSpace="http://www.sig3d.org/codelists/citygml/2.0/building/2.0/_AbstractBuilding_roofType.xml">1030</bldg:roofType>
|
||||
<bldg:measuredHeight uom="m">6.52</bldg:measuredHeight>
|
||||
<bldg:storeysAboveGround>2</bldg:storeysAboveGround>
|
||||
<bldg:storeysBelowGround>0</bldg:storeysBelowGround>
|
||||
<bldg:lod1Solid>
|
||||
<gml:Solid>
|
||||
<gml:exterior>
|
||||
<gml:CompositeSurface>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon>
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList srsDimension="3">457842 5439083 111.8 457842 5439093 111.8 457854 5439093 111.8 457854 5439083 111.8 457842 5439083 111.8 </gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon>
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList srsDimension="3">457842 5439083 118.31769 457854 5439083 118.31769 457854 5439093 118.31769 457842 5439093 118.31769 457842 5439083 118.31769 </gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon>
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList srsDimension="3">457842 5439083 111.8 457842 5439083 118.31769 457842 5439093 118.31769 457842 5439093 111.8 457842 5439083 111.8 </gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon>
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList srsDimension="3">457842 5439093 111.8 457842 5439093 118.31769 457854 5439093 118.31769 457854 5439093 111.8 457842 5439093 111.8 </gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon>
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList srsDimension="3">457854 5439093 111.8 457854 5439093 118.31769 457854 5439083 118.31769 457854 5439083 111.8 457854 5439093 111.8 </gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
<gml:surfaceMember>
|
||||
<gml:Polygon>
|
||||
<gml:exterior>
|
||||
<gml:LinearRing>
|
||||
<gml:posList srsDimension="3">457854 5439083 111.8 457854 5439083 118.31769 457842 5439083 118.31769 457842 5439083 111.8 457854 5439083 111.8 </gml:posList>
|
||||
</gml:LinearRing>
|
||||
</gml:exterior>
|
||||
</gml:Polygon>
|
||||
</gml:surfaceMember>
|
||||
</gml:CompositeSurface>
|
||||
</gml:exterior>
|
||||
</gml:Solid>
|
||||
</bldg:lod1Solid>
|
||||
<bldg:address>
|
||||
<core:Address>
|
||||
<core:xalAddress>
|
||||
<xAL:AddressDetails>
|
||||
<xAL:Locality Type="Town">
|
||||
<xAL:LocalityName>Eggenstein-Leopoldshafen</xAL:LocalityName>
|
||||
<xAL:Thoroughfare Type="Street">
|
||||
<xAL:ThoroughfareNumber>4711</xAL:ThoroughfareNumber>
|
||||
<xAL:ThoroughfareName>Spöcker Straße</xAL:ThoroughfareName>
|
||||
</xAL:Thoroughfare>
|
||||
<xAL:PostalCode>
|
||||
<xAL:PostalCodeNumber>76344</xAL:PostalCodeNumber>
|
||||
</xAL:PostalCode>
|
||||
</xAL:Locality>
|
||||
</xAL:AddressDetails>
|
||||
</core:xalAddress>
|
||||
</core:Address>
|
||||
</bldg:address>
|
||||
</bldg:Building>
|
||||
</core:cityObjectMember>
|
||||
</core:CityModel>
|
File diff suppressed because it is too large
Load Diff
|
@ -22298,6 +22298,10 @@
|
|||
-73.576898276422085,
|
||||
45.493440825460823
|
||||
],
|
||||
[
|
||||
-73.576894294282425,
|
||||
45.493438920982065
|
||||
],
|
||||
[
|
||||
-73.576887226721908,
|
||||
45.493435542959816
|
||||
|
@ -23733,6 +23737,10 @@
|
|||
-73.577189938818421,
|
||||
45.496590580959172
|
||||
],
|
||||
[
|
||||
-73.577182794574895,
|
||||
45.496587194332115
|
||||
],
|
||||
[
|
||||
-73.577172439176323,
|
||||
45.496582294545249
|
||||
|
@ -40792,7 +40800,7 @@
|
|||
[
|
||||
-73.577438364340622,
|
||||
45.497229849401236
|
||||
],
|
||||
],
|
||||
[
|
||||
-73.577429107909751,
|
||||
45.497234258613375
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,573 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<library name="LCA">
|
||||
<Fuels>
|
||||
<fuel id="1" name= "Black_coal">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh" > 0.32 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="2" name= "Brown_coal">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.4 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="3" name= "Brown_coal_briquette">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.4 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="4" name= "Brown_coal_coke">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.5 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="5" name= "CNG">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.18 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="6" name= "Coal_coke">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.39 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="7" name= "Crude_oil">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.27 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="8" name= "Diesel_Machine">
|
||||
<carbon_emission_factor unit= "kgCO2/ liter"> 4.16 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="9" name= "Diesel_Vehicle">
|
||||
<carbon_emission_factor unit= "kgCO2/ liter"> 2.24 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="10" name= "Ethane">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.2 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="11" name= "Fuel_oil">
|
||||
<carbon_emission_factor unit= "kgCO2/ liter"> 3.19 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="12" name= "Gas_flared">
|
||||
<carbon_emission_factor unit= "kgCO2/ kg"> 3.53 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="13" name= "Kerosene">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.27 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="14" name= "LNG">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.21 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="15" name= "LPG">
|
||||
<carbon_emission_factor unit= "kgCO2/ liter"> 1.69 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="16" name= "Natural_gas">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.21 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="17" name= "Petroleum_coke">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.35 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="18" name= "UNG">
|
||||
<carbon_emission_factor unit= "kgCO2/ kWh"> 0.18 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="19" name= "Biodiesel">
|
||||
<carbon_emission_factor unit= "kgCO2/ liter"> 0.81 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="20" name= "Bioethanol">
|
||||
<carbon_emission_factor unit= "kgCO2/ kg"> 1.21 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="21" name= "Biogas">
|
||||
<carbon_emission_factor unit= "kgCO2/ kg"> 1.61 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="22" name= "Biomass">
|
||||
<carbon_emission_factor unit= "kgCO2/ kg"> 0.11 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="23" name= "Methanol">
|
||||
<carbon_emission_factor unit= "kgCO2/ kg"> 0.3 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="24" name= "Petrol_eightyfive_ethanol">
|
||||
<carbon_emission_factor unit= "kgCO2/ kg"> 1.16 </carbon_emission_factor>
|
||||
</fuel>
|
||||
<fuel id="25" name= "Steam">
|
||||
<carbon_emission_factor unit= "kgCO2/ kg"> 0.61 </carbon_emission_factor>
|
||||
</fuel>
|
||||
</Fuels>
|
||||
<Machines>
|
||||
<machine name= "Rock_drill">
|
||||
<work_efficiency unit= "h/m3"> 0.347 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 16.5 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Hydraulic_hammer">
|
||||
<work_efficiency unit= "h/m3"> 0.033 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kg_fuel/h"> 25.2 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kg_fuel"> 4.16 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Crawler_bulldozer">
|
||||
<work_efficiency unit= "h/m3"> 0.027 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kg_fuel/h3"> 16.8 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kg_fuel"> 2.239 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Crawler_excavator">
|
||||
<work_efficiency unit= "h/m3"> 0.023 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kg_fuel/h"> 16.8 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kg_fuel"> 2.239 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Crawler_hydraulic_rock_crusher">
|
||||
<work_efficiency unit= "h/m3"> 0.109 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kg_fuel/h"> 25.2 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kg_fuel"> 2.239 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Mobile_recycling_equipment">
|
||||
<work_efficiency unit= "h/ton"> 0.003 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kg_fuel/h"> 16.4 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kg_fuel"> 4.16 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Vibration_feeder">
|
||||
<work_efficiency unit= "h/ton"> 0.002 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 11 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Jaw_crusher">
|
||||
<work_efficiency unit= "h/ton"> 0.002 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 90 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Electromagnetic_separator">
|
||||
<work_efficiency unit= "h/ton"> 0.002 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 10 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Wind_sorting_machine">
|
||||
<work_efficiency unit= "h/ton"> 0.002 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 11 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Impact_crusher">
|
||||
<work_efficiency unit= "h/ton"> 0.002 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 132 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Double_circular_vibrating_plug">
|
||||
<work_efficiency unit= " h/ton "> 0.002 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 15 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kW"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Spiral_sand_washing_machine">
|
||||
<work_efficiency unit= "h/ton"> 0.002 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 5.5 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
<machine name= "Conveyor_belts">
|
||||
<work_efficiency unit= "h/ton"> 0.002 </work_efficiency>
|
||||
<energy_consumption_rate unit= "kWh/h"> 22.5 </energy_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</machine>
|
||||
</Machines>
|
||||
<Vehicles>
|
||||
<vehicle name= "Freight_lorry_18_ton">
|
||||
<fuel_consumption_rate unit= "kg_fuel/ton.km"> 0.0123 </fuel_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kg_fuel"> 2.239 </carbon_emission_factor>
|
||||
</vehicle>
|
||||
<vehicle name= "Freight_train">
|
||||
<fuel_consumption_rate unit= "kWh/ton.km"> 0.042 </fuel_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 0.918 </carbon_emission_factor>
|
||||
</vehicle>
|
||||
<vehicle name= "Freight_ship">
|
||||
<fuel_consumption_rate unit= "kWh/ton.km"> 0.01 </fuel_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 1.00000 </carbon_emission_factor>
|
||||
</vehicle>
|
||||
<vehicle name= "Freight_Air">
|
||||
<fuel_consumption_rate unit= "kWh/ton.km"> 1.3 </fuel_consumption_rate>
|
||||
<carbon_emission_factor unit= "kgCO2/kWh"> 1.00000 </carbon_emission_factor>
|
||||
</vehicle>
|
||||
</Vehicles>
|
||||
<Building_materials>
|
||||
<Bricks>
|
||||
<brick id="1" type= "clay brick">
|
||||
<density unit= "ton/m3"> 1.8 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 560 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0.7 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</brick>
|
||||
<brick id="2" type= "light clay brick">
|
||||
<density unit= "ton/m3"> 1.2 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 310 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0.7 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</brick>
|
||||
<brick id="3" type= "refractory">
|
||||
<density unit= "ton/m3"> 2 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 3080 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0.7 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</brick>
|
||||
<brick id="4" type= "sand-lime brick">
|
||||
<density unit= "ton/m3"> 1.4 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 300 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0.3 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0.7 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</brick>
|
||||
</Bricks>
|
||||
<Concretes>
|
||||
<concrete id="1" type= "light weight expanded clay">
|
||||
<density unit= "ton/m3"> 1.6 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 900 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="2" type= "lightweight Expanded perlite">
|
||||
<density unit= "ton/m3"> 1.6 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 2340 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="3" type= "lightweight expanded vermiculite">
|
||||
<density unit= "ton/m3"> 1.6 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 1570 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="4" type= "lightweight polystyrene">
|
||||
<density unit= "ton/m3"> 1.4 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 1840 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="5" type= "lightweight pumice">
|
||||
<density unit= "ton/m3"> 1.3 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 410 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="6" type= "concrete 20 MPa">
|
||||
<density unit= "ton/m3"> 2.3 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 160 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="7" type= "concrete 25 MPa">
|
||||
<density unit= "ton/m3"> 2.3 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 170 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="8" type= "concrete 30-32 MPa">
|
||||
<density unit= "ton/m3"> 2.3 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 230 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="9" type= "concrete 35 MPae">
|
||||
<density unit= "ton/m3"> 2.4 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 240 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="10" type= "concrete 50 MPa">
|
||||
<density unit= "ton/m3"> 2.4 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 280 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="11" type= "concrete block">
|
||||
<density unit= "ton/m3"> 2.3 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 170 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
<concrete id="12" type= "concrete roof tile">
|
||||
<density unit= "ton/m3"> 1.2 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 440 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</concrete>
|
||||
</Concretes>
|
||||
<glasses>
|
||||
<glass id="1" type= "flat glass, coated">
|
||||
<density unit= "ton/m3"> 2.58 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 2660 </embodied_carbon>
|
||||
<recycling_ratio> 0.95 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.05 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</glass>
|
||||
<glass id="2" type= "glass fibre">
|
||||
<density unit= "ton/m3"> 2.58 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 5260 </embodied_carbon>
|
||||
<recycling_ratio> 0.95 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.05 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</glass>
|
||||
</glasses>
|
||||
<Insulations>
|
||||
<Insulation id="1" type= "cellulose fibre">
|
||||
<density unit= "ton/m3"> 0.06 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 1760 </embodied_carbon>
|
||||
<recycling_ratio> 0.9 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</Insulation>
|
||||
<Insulation id="2" type= "cork slab">
|
||||
<density unit= "ton/m3"> 0.122 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 3080 </embodied_carbon>
|
||||
<recycling_ratio> 0.9 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</Insulation>
|
||||
<Insulation id="3" type= "polystyren foam">
|
||||
<density unit= "ton/m3"> 0.028 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 3180 </embodied_carbon>
|
||||
<recycling_ratio> 0.9 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</Insulation>
|
||||
<Insulation id="4" type= "polystyrene 10% recycled">
|
||||
<density unit= "ton/m3"> 0.024 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 5140 </embodied_carbon>
|
||||
<recycling_ratio> 0.9 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</Insulation>
|
||||
<Insulation id="5" type= "stone wool">
|
||||
<density unit= "ton/m3"> 0.1 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 6040 </embodied_carbon>
|
||||
<recycling_ratio> 0.9 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</Insulation>
|
||||
<Insulation id="6" type= "foam glass">
|
||||
<density unit= "ton/m3"> 0.3 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 5380 </embodied_carbon>
|
||||
<recycling_ratio> 0.9 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</Insulation>
|
||||
<Insulation id="7" type= "glass wool mat">
|
||||
<density unit= "ton/m3"> 0.032 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 2150 </embodied_carbon>
|
||||
<recycling_ratio> 0.9 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</Insulation>
|
||||
</Insulations>
|
||||
<woods>
|
||||
<wood id="1" type= "fiberboard, hard">
|
||||
<density unit= "ton/m3"> 0.9 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 3420 </embodied_carbon>
|
||||
<recycling_ratio> 0.6 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.4 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</wood>
|
||||
<wood id="2" type= "three layerd laminated board">
|
||||
<density unit= "ton/m3"> 0.7 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 1430 </embodied_carbon>
|
||||
<recycling_ratio> 0.6 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.4 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</wood>
|
||||
<wood id="3" type= "fibreboard, soft">
|
||||
<density unit= "ton/m3"> 0.65 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 2780 </embodied_carbon>
|
||||
<recycling_ratio> 0.6 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.4 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</wood>
|
||||
<wood id="4" type= "plywood">
|
||||
<density unit= "ton/m3"> 0.72 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 2190 </embodied_carbon>
|
||||
<recycling_ratio> 0.6 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.4 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</wood>
|
||||
</woods>
|
||||
<coverings>
|
||||
<covering id="1" type= "acrylic filler">
|
||||
<density unit= "ton/m3"> 1.43 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 1070 </embodied_carbon>
|
||||
<recycling_ratio> 0 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0 </company_recycling_ratio>
|
||||
<landfilling_ratio> 1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="2" type= "anhydrite floor">
|
||||
<density unit= "ton/m3"> 1.43 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 240 </embodied_carbon>
|
||||
<recycling_ratio> 0 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0 </company_recycling_ratio>
|
||||
<landfilling_ratio> 1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="3" type= "base plaster">
|
||||
<density unit= "ton/m3"> 1.43 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 430 </embodied_carbon>
|
||||
<recycling_ratio> 0 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0 </company_recycling_ratio>
|
||||
<landfilling_ratio> 1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="4" type= "cement cast plaster floor">
|
||||
<density unit= "ton/m3"> 1.43 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 340 </embodied_carbon>
|
||||
<recycling_ratio> 0 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0 </company_recycling_ratio>
|
||||
<landfilling_ratio> 1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="5" type= "cement tile">
|
||||
<density unit= "ton/m3"> 1.2 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 440 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="6" type= "ceramic tile">
|
||||
<density unit= "ton/m3"> 2.1 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 1410 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="7" type= "clay plaster">
|
||||
<density unit= "ton/m3"> 1.43 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 250 </embodied_carbon>
|
||||
<recycling_ratio> 0 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 0 </company_recycling_ratio>
|
||||
<landfilling_ratio> 1 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="7" type= "fiber cement corrugated slab">
|
||||
<density unit= "ton/m3"> 1.44 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 1480 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="7" type= "fiber cement facing tile">
|
||||
<density unit= "ton/m3"> 1.44 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 2220 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="7" type= "gypsum fibreboard">
|
||||
<density unit= "ton/m3"> 1.27 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 3960 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
<covering id="7" type= "gypsum plaster board">
|
||||
<density unit= "ton/m3"> 1.15 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 760 </embodied_carbon>
|
||||
<recycling_ratio> 0.8 </recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.2 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</covering>
|
||||
</coverings>
|
||||
<metals>
|
||||
<metal id="1" type= "steel">
|
||||
<density unit= "ton/m3"> 8 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 3160 </embodied_carbon>
|
||||
<recycling_ratio> 0.98</recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.02 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</metal>
|
||||
<metal id="2" type= "aluminium">
|
||||
<density unit= "ton/m3"> 2.7 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 5370 </embodied_carbon>
|
||||
<recycling_ratio> 0.98</recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.02 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</metal>
|
||||
<metal id="3" type= "reinforcing steel">
|
||||
<density unit= "ton/m3"> 7.85 </density>
|
||||
<embodied_carbon unit= "kgCO2/ton"> 3910 </embodied_carbon>
|
||||
<recycling_ratio> 0.98</recycling_ratio>
|
||||
<onsite_recycling_ratio> 0 </onsite_recycling_ratio>
|
||||
<company_recycling_ratio> 1 </company_recycling_ratio>
|
||||
<landfilling_ratio> 0.02 </landfilling_ratio>
|
||||
<cost unit= "...."> .... </cost>
|
||||
</metal>
|
||||
</metals>
|
||||
</Building_materials>
|
||||
</library>
|
|
@ -1,18 +0,0 @@
|
|||
{ "type": "FeatureCollection",
|
||||
"features": [
|
||||
{ "type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[ [[-73.5027962600162, 45.6572759731914], [-73.5027463586105, 45.6572669735158], [-73.5027513584185, 45.6572530729948], [-73.5026715592026, 45.6572412737672], [-73.5026410593539, 45.6573430727752], [-73.5027703584728, 45.6573621728624], [-73.5027962600162, 45.6572759731914]] ]
|
||||
]
|
||||
|
||||
},
|
||||
"properties": {
|
||||
"geom": {"type": "Polygon", "crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:EPSG::4326"}}, "coordinates": [[[3849322.0855625975, 6060583.24800576], [3849326.3956304314, 6060584.796717078], [3849327.0180495544, 6060583.089519385], [3849333.725799462, 6060585.837955164], [3849328.71788522, 6060598.03498192], [3849317.850609142, 6060593.57976506], [3849322.0855625975, 6060583.24800576]]]},
|
||||
"height": 13.0790429485,
|
||||
"year_built": 2000
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
2
hub/unittests/tests_outputs/.gitignore
vendored
2
hub/unittests/tests_outputs/.gitignore
vendored
|
@ -1,4 +1,2 @@
|
|||
# Ignore everything in this directory
|
||||
.gitignore
|
||||
# Except this file
|
||||
!.gitignore
|
|
@ -24,4 +24,5 @@ geopandas
|
|||
triangle
|
||||
psycopg2-binary
|
||||
Pillow
|
||||
pathlib
|
||||
pathlib
|
||||
pickle5
|
1
setup.py
1
setup.py
|
@ -87,6 +87,7 @@ setup(
|
|||
('hub/catalog_factories/greenery/ecore_greenery', glob.glob('hub/catalog_factories/greenery/ecore_greenery/*.ecore')),
|
||||
('hub/data/construction.', glob.glob('hub/data/construction/*')),
|
||||
('hub/data/customized_imports', glob.glob('hub/data/customized_imports/*.xml')),
|
||||
('data/geolocation', glob.glob('hub/data/geolocation/*.txt')),
|
||||
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.xml')),
|
||||
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.insel')),
|
||||
('hub/data/energy_systems', glob.glob('hub/data/energy_systems/*.xlsx')),
|
||||
|
|
Loading…
Reference in New Issue
Block a user