Merge branch 'main' into hp_results

This commit is contained in:
Peter Yefi 2023-03-20 16:55:45 -04:00
commit ff55b502a6
69 changed files with 2214 additions and 1546 deletions

View File

@ -8,12 +8,13 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
class Catalog:
"""
Catalogs base class not implemented instance of the Catalog base class, catalog_factories will inherit from this class.
Catalogs base class not implemented instance of the Catalog base class,
catalog_factories will inherit from this class.
"""
def names(self, category=None):
"""
Base property to return the catalog entries names
Base property to return the catalog entries names.
:return: Catalog names filter by category if provided
"""
raise NotImplementedError

View File

@ -1,21 +1,21 @@
"""
Cost catalog
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import xmltodict
from hub.catalog_factories.catalog import Catalog
from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost
from hub.catalog_factories.data_models.cost.envelope import Envelope
from hub.catalog_factories.data_models.cost.systems import Systems
from hub.catalog_factories.data_models.cost.hvac import Hvac
from hub.catalog_factories.data_models.cost.operational_cost import OperationalCost
from hub.catalog_factories.data_models.cost.income import Income
from hub.catalog_factories.data_models.cost.archetype import Archetype
from hub.catalog_factories.data_models.cost.content import Content
from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost
from hub.catalog_factories.data_models.cost.chapter import Chapter
from hub.catalog_factories.data_models.cost.item_description import ItemDescription
from hub.catalog_factories.data_models.cost.operational_cost import OperationalCost
from hub.catalog_factories.data_models.cost.fuel import Fuel
from hub.catalog_factories.data_models.cost.income import Income
from hub.catalog_factories.data_models.cost.cost_helper import CostHelper
class MontrealCustomCatalog(Catalog):
@ -28,90 +28,93 @@ class MontrealCustomCatalog(Catalog):
self._content = Content(self._load_archetypes())
@staticmethod
def _get_threesome(entry):
_reposition = float(entry['reposition']['#text'])
_investment = float(entry['initial_investment']['#text'])
_lifetime = float(entry['lifetime_equipment']['#text'])
return _reposition, _investment, _lifetime
def _item_with_threesome(entry, item_type):
_reposition = float(entry[item_type]['reposition']['#text'])
_reposition_unit = entry[item_type]['reposition']['@cost_unit']
_investment = float(entry[item_type]['investment_cost']['#text'])
_investment_unit = entry[item_type]['investment_cost']['@cost_unit']
_lifetime = float(entry[item_type]['lifetime_equipment']['#text'])
_item_description = ItemDescription(item_type,
initial_investment=_investment,
initial_investment_unit=_investment_unit,
reposition=_reposition,
reposition_unit=_reposition_unit,
lifetime=_lifetime)
return _item_description
@staticmethod
def _item_with_refurbishment_values(entry, item_type):
_refurbishment = float(entry[item_type]['refurbishment_cost']['#text'])
_refurbishment_unit = entry[item_type]['refurbishment_cost']['@cost_unit']
_item_description = ItemDescription(item_type,
refurbishment=_refurbishment,
refurbishment_unit=_refurbishment_unit)
return _item_description
def _get_capital_costs(self, entry):
structural = float(entry['structural']['#text'])
sub_structural = float(entry['sub_structural']['#text'])
surface_finish = float(entry['surface_finish']['#text'])
engineer = float(entry['engineer']['#text'])
opaque_reposition, opaque_initial_investment, opaque_lifetime = \
self._get_threesome(entry['envelope']['opaque'])
transparent_reposition, transparent_initial_investment, transparent_lifetime = \
self._get_threesome(entry['envelope']['transparent'])
envelope = Envelope(opaque_reposition,
opaque_initial_investment,
opaque_lifetime,
transparent_reposition,
transparent_initial_investment,
transparent_lifetime)
heating_equipment_reposition, heating_equipment_initial_investment, heating_equipment_lifetime = \
self._get_threesome(entry['systems']['hvac']['heating_equipment_cost'])
heating_equipment_reposition = heating_equipment_reposition / 1000
heating_equipment_initial_investment = heating_equipment_initial_investment / 1000
cooling_equipment_reposition, cooling_equipment_initial_investment, cooling_equipment_lifetime = \
self._get_threesome(entry['systems']['hvac']['cooling_equipment_cost'])
cooling_equipment_reposition = cooling_equipment_reposition / 1000
cooling_equipment_initial_investment = cooling_equipment_initial_investment / 1000
general_hvac_equipment_reposition, general_hvac_equipment_initial_investment, general_hvac_equipment_lifetime = \
self._get_threesome(entry['systems']['hvac']['general_hvac_equipment_cost'])
general_hvac_equipment_reposition = general_hvac_equipment_reposition * 3600
general_hvac_equipment_initial_investment = general_hvac_equipment_initial_investment * 3600
hvac = Hvac(heating_equipment_reposition, heating_equipment_initial_investment, heating_equipment_lifetime,
cooling_equipment_reposition, cooling_equipment_initial_investment, cooling_equipment_lifetime,
general_hvac_equipment_reposition, general_hvac_equipment_initial_investment,
general_hvac_equipment_lifetime)
general_chapters = []
chapters_titles = CostHelper().chapters_in_lod1
items_list = []
item_type = 'B10_superstructure'
item_description = self._item_with_refurbishment_values(entry, item_type)
items_list.append(item_description)
for item in entry['B20_envelope']:
item_type = item
item_description = self._item_with_refurbishment_values(entry['B20_envelope'], item_type)
items_list.append(item_description)
item_type = 'B30_roofing'
item_description = self._item_with_refurbishment_values(entry, item_type)
items_list.append(item_description)
general_chapters.append(Chapter('B_shell', items_list))
photovoltaic_system_reposition, photovoltaic_system_initial_investment, photovoltaic_system_lifetime = \
self._get_threesome(entry['systems']['photovoltaic_system'])
other_conditioning_systems_reposition, other_conditioning_systems_initial_investment, \
other_conditioning_systems_lifetime = self._get_threesome(entry['systems']['other_systems'])
lighting_reposition, lighting_initial_investment, lighting_lifetime = \
self._get_threesome(entry['systems']['lighting'])
systems = Systems(hvac,
photovoltaic_system_reposition,
photovoltaic_system_initial_investment,
photovoltaic_system_lifetime,
other_conditioning_systems_reposition,
other_conditioning_systems_initial_investment,
other_conditioning_systems_lifetime,
lighting_reposition,
lighting_initial_investment,
lighting_lifetime)
_capital_cost = CapitalCost(structural,
sub_structural,
envelope,
systems,
surface_finish,
engineer)
items_list = []
item_type = 'D301010_photovoltaic_system'
item_description = self._item_with_threesome(entry['D30_hvac']['D3010_energy_supply'], item_type)
items_list.append(item_description)
item_type_list = ['D3020_heat_generating_systems', 'D3030_cooling_generation_systems', 'D3040_distribution_systems',
'D3080_other_hvac_ahu']
for item_type in item_type_list:
item_description = self._item_with_threesome(entry['D30_hvac'], item_type)
items_list.append(item_description)
item_type = 'D5020lighting_and_branch_wiring'
item_description = self._item_with_threesome(entry['D50_electrical'], item_type)
items_list.append(item_description)
general_chapters.append(Chapter('D_services', items_list))
design_allowance = float(entry['Z_allowances_overhead_profit']['Z10_design_allowance']['#text']) / 100
overhead_and_profit = float(entry['Z_allowances_overhead_profit']['Z10_overhead_and_profit']['#text']) / 100
_capital_cost = CapitalCost(general_chapters, design_allowance, overhead_and_profit)
return _capital_cost
@staticmethod
def _get_operational_costs(entry):
fuel_type = entry['fuel']['@fuel_type']
fuel_fixed_operational_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text'])
fuel_fixed_operational_peak = float(entry['fuel']['fixed']['fixed_power']['#text']) / 1000
fuel_variable_operational = float(entry['fuel']['variable']['#text']) / 1000 / 3600
fuels = []
for item in entry['fuels']:
fuel_type = item['fuel']['@fuel_type']
fuel_variable = float(entry['fuel']['variable']['#text'])
fuel_variable_units = float(entry['fuel']['variable']['@cost_unit'])
fuel_fixed_monthly = None
fuel_fixed_peak = None
if fuel_type == 'electricity':
fuel_fixed_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text'])
fuel_fixed_peak = float(entry['fuel']['fixed']['fixed_power']['#text']) / 1000
elif fuel_type == 'gas':
fuel_fixed_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text'])
fuel = Fuel(fuel_type,
fixed_monthly=fuel_fixed_monthly,
fixed_power=fuel_fixed_peak,
variable=fuel_variable,
variable_units=fuel_variable_units)
fuels.append(fuel)
heating_equipment_maintenance = float(entry['maintenance']['heating_equipment']['#text']) / 1000
cooling_equipment_maintenance = float(entry['maintenance']['cooling_equipment']['#text']) / 1000
general_hvac_equipment_maintenance = float(entry['maintenance']['general_hvac_equipment']['#text']) * 3600
photovoltaic_system_maintenance = float(entry['maintenance']['photovoltaic_system']['#text'])
other_systems_maintenance = float(entry['maintenance']['other_systems']['#text'])
co2_emissions = float(entry['CO2_cost']['#text'])
_operational_cost = OperationalCost(fuel_type,
fuel_fixed_operational_monthly,
fuel_fixed_operational_peak,
fuel_variable_operational,
_operational_cost = OperationalCost(fuels,
heating_equipment_maintenance,
cooling_equipment_maintenance,
general_hvac_equipment_maintenance,
photovoltaic_system_maintenance,
other_systems_maintenance,
co2_emissions)
return _operational_cost
@ -121,7 +124,10 @@ class MontrealCustomCatalog(Catalog):
for archetype in archetypes:
function = archetype['@function']
municipality = archetype['@municipality']
currency = archetype['@currency']
country = archetype['@country']
lod = float(archetype['@lod'])
currency = archetype['currency']
print(currency)
capital_cost = self._get_capital_costs(archetype['capital_cost'])
operational_cost = self._get_operational_costs(archetype['operational_cost'])
end_of_life_cost = float(archetype['end_of_life_cost']['#text'])
@ -129,17 +135,21 @@ class MontrealCustomCatalog(Catalog):
hvac = float(archetype['incomes']['subsidies']['hvac_subsidy']['#text'])
photovoltaic_system = float(archetype['incomes']['subsidies']['photovoltaic_subsidy']['#text'])
electricity_exports = float(archetype['incomes']['energy_exports']['electricity']['#text']) / 1000 / 3600
heat_exports = float(archetype['incomes']['energy_exports']['heat']['#text']) / 1000 / 3600
co2 = float(archetype['incomes']['CO2_income']['#text'])
income = Income(construction, hvac, photovoltaic_system, electricity_exports, heat_exports, co2)
_catalog_archetypes.append(Archetype(function,
reduction_tax = float(archetype['incomes']['tax_reduction']['#text']) / 100
income = Income(construction_subsidy=construction,
hvac_subsidy=hvac,
photovoltaic_subsidy=photovoltaic_system,
electricity_export=electricity_exports,
reductions_tax=reduction_tax)
_catalog_archetypes.append(Archetype(lod,
function,
municipality,
country,
currency,
capital_cost,
operational_cost,
end_of_life_cost,
income))
return _catalog_archetypes
def names(self, category=None):

View File

@ -1,8 +1,8 @@
"""
Archetype catalog Cost
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost
@ -11,9 +11,21 @@ from hub.catalog_factories.data_models.cost.income import Income
class Archetype:
def __init__(self, function, municipality, currency, capital_cost, operational_cost, end_of_life_cost, income):
def __init__(self,
lod,
function,
municipality,
country,
currency,
capital_cost,
operational_cost,
end_of_life_cost,
income):
self._lod = lod
self._function = function
self._municipality = municipality
self._country = country
self._currency = currency
self._capital_cost = capital_cost
self._operational_cost = operational_cost
@ -26,7 +38,15 @@ class Archetype:
Get name
:return: string
"""
return f'{self._municipality}_{self._function}'
return f'{self._country}_{self._municipality}_{self._function}_{self._lod}'
@property
def lod(self):
"""
Get level of detail of the catalog
:return: string
"""
return self._lod
@property
def function(self):
@ -44,6 +64,14 @@ class Archetype:
"""
return self._municipality
@property
def country(self):
"""
Get country
:return: string
"""
return self._country
@property
def currency(self):
"""

View File

@ -1,68 +1,40 @@
"""
Cost catalog CapitalCost
Capital costs included in the catalog
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from hub.catalog_factories.data_models.cost.envelope import Envelope
from hub.catalog_factories.data_models.cost.systems import Systems
from typing import List
from hub.catalog_factories.data_models.cost.chapter import Chapter
class CapitalCost:
def __init__(self, structural, sub_structural, envelope, systems, surface_finish, engineer):
self._structural = structural
self._sub_structural = sub_structural
self._envelope = envelope
self._systems = systems
self._surface_finish = surface_finish
self._engineer = engineer
def __init__(self, general_chapters, design_allowance, overhead_and_profit):
self._general_chapters = general_chapters
self._design_allowance = design_allowance
self._overhead_and_profit = overhead_and_profit
@property
def structural(self):
def general_chapters(self) -> List[Chapter]:
"""
Get structural cost per building volume in currency/m3
Get general chapters in capital costs
:return: [Chapter]
"""
return self._general_chapters
@property
def design_allowance(self):
"""
Get design allowance in percentage (-)
:return: float
"""
return self._structural
return self._design_allowance
@property
def sub_structural(self):
def overhead_and_profit(self):
"""
Get sub structural cost per building foot-print in currency/m2
Get overhead profit in percentage (-)
:return: float
"""
return self._sub_structural
@property
def envelope(self) -> Envelope:
"""
Get envelope cost
:return: Envelope
"""
return self._envelope
@property
def systems(self) -> Systems:
"""
Get systems cost
:return: Systems
"""
return self._systems
@property
def surface_finish(self):
"""
Get surface finish cost per external surfaces areas in currency/m2
:return: float
"""
return self._surface_finish
@property
def engineer(self):
"""
Get engineer cost in %
:return: float
"""
return self._engineer
return self._overhead_and_profit

View File

@ -0,0 +1,32 @@
"""
Cost chapter description
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import List
from hub.catalog_factories.data_models.cost.item_description import ItemDescription
class Chapter:
def __init__(self, chapter_type, items):
self._chapter_type = chapter_type
self._items = items
@property
def chapter_type(self):
"""
Get chapter type
:return: str
"""
return self._chapter_type
@property
def items(self) -> List[ItemDescription]:
"""
Get list of items contained in the chapter
:return: [str]
"""
return self._items

View File

@ -0,0 +1,48 @@
"""
Cost helper
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import hub.helpers.constants as cte
from typing import Dict
class CostHelper:
"""
Cost helper class
"""
_costs_units = {
'currency/m2': cte.CURRENCY_PER_SQM,
'currency/m3': cte.CURRENCY_PER_CBM,
'currency/kW': cte.CURRENCY_PER_KW,
'currency/kWh': cte.CURRENCY_PER_KWH,
'currency/month': cte.CURRENCY_PER_MONTH,
'currency/l': cte.CURRENCY_PER_LITRE,
'currency/kg': cte.CURRENCY_PER_KG,
'currency/(m3/h)': cte.CURRENCY_PER_CBM_PER_HOUR,
'%': cte.PERCENTAGE
}
_chapters_in_lod1 = {
'B_shell': cte.SUPERSTRUCTURE,
'D_services': cte.ENVELOPE,
'Z_allowances_overhead_profit': cte.ALLOWANCES_OVERHEAD_PROFIT
}
@property
def costs_units(self) -> Dict:
"""
List of supported costs units
:return: dict
"""
return self._costs_units
@property
def chapters_in_lod1(self) -> Dict:
"""
List of chapters included in lod 1
:return: dict
"""
return self._chapters_in_lod1

View File

@ -1,66 +0,0 @@
"""
Envelope costs from Cost catalog
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
class Envelope:
def __init__(self, opaque_reposition, opaque_initial_investment, opaque_lifetime,
transparent_reposition, transparent_initial_investment, transparent_lifetime):
self._opaque_reposition = opaque_reposition
self._opaque_initial_investment = opaque_initial_investment
self._opaque_lifetime = opaque_lifetime
self._transparent_reposition = transparent_reposition
self._transparent_initial_investment = transparent_initial_investment
self._transparent_lifetime = transparent_lifetime
@property
def opaque_reposition(self):
"""
Get reposition costs for opaque envelope per area of external opaque surfaces in currency/m2
:return: float
"""
return self._opaque_reposition
@property
def opaque_initial_investment(self):
"""
Get initial investment for opaque envelope per area of external opaque surfaces in currency/m2
:return: float
"""
return self._opaque_initial_investment
@property
def opaque_lifetime(self):
"""
Get lifetime of opaque envelope in years
:return: float
"""
return self._opaque_lifetime
@property
def transparent_reposition(self):
"""
Get reposition costs for transparent envelope per area of windows in currency/m2
:return: float
"""
return self._transparent_reposition
@property
def transparent_initial_investment(self):
"""
Get initial investment for transparent envelope per area of windows in currency/m2
:return: float
"""
return self._transparent_initial_investment
@property
def transparent_lifetime(self):
"""
Get lifetime of transparent envelope in years
:return: float
"""
return self._transparent_lifetime

View File

@ -0,0 +1,54 @@
"""
Cost fuel
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union
class Fuel:
def __init__(self, fuel_type,
fixed_monthly=None,
fixed_power=None,
variable=None,
variable_units=None):
self._fuel_type = fuel_type
self._fixed_monthly = fixed_monthly
self._fixed_power = fixed_power
self._variable = variable
self._variable_units = variable_units
@property
def type(self):
"""
Get fuel type
:return: str
"""
return self._fuel_type
@property
def fixed_monthly(self) -> Union[None, float]:
"""
Get fixed operational costs in currency per month
:return: None or float
"""
return self._fixed_monthly
@property
def fixed_power(self) -> Union[None, float]:
"""
Get fixed operational costs depending on the peak power consumed in currency per month per kW
:return: None or float
"""
return self._fixed_power
@property
def variable(self) -> Union[tuple[None, None], tuple[float, str]]:
"""
Get variable costs in given units
:return: None, None or float, str
"""
return self._variable, self._variable_units

View File

@ -1,96 +0,0 @@
"""
Hvac costs
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
"""
class Hvac:
def __init__(self, heating_equipment_reposition, heating_equipment_initial_investment,
heating_equipment_lifetime, cooling_equipment_reposition,
cooling_equipment_initial_investment, cooling_equipment_lifetime,
general_hvac_equipment_reposition, general_hvac_equipment_initial_investment,
general_hvac_equipment_lifetime):
self._heating_equipment_reposition = heating_equipment_reposition
self._heating_equipment_initial_investment = heating_equipment_initial_investment
self._heating_equipment_lifetime = heating_equipment_lifetime
self._cooling_equipment_reposition = cooling_equipment_reposition
self._cooling_equipment_initial_investment = cooling_equipment_initial_investment
self._cooling_equipment_lifetime = cooling_equipment_lifetime
self._general_hvac_equipment_reposition = general_hvac_equipment_reposition
self._general_hvac_equipment_initial_investment = general_hvac_equipment_initial_investment
self._general_hvac_equipment_lifetime = general_hvac_equipment_lifetime
@property
def heating_equipment_reposition(self):
"""
Get reposition costs of heating equipment per peak-load in currency/W
:return: float
"""
return self._heating_equipment_reposition
@property
def heating_equipment_initial_investment(self):
"""
Get initial investment costs of heating equipment per peak-load in currency/W
:return: float
"""
return self._heating_equipment_initial_investment
@property
def heating_equipment_lifetime(self):
"""
Get lifetime of heating equipment in years
:return: float
"""
return self._heating_equipment_lifetime
@property
def cooling_equipment_reposition(self):
"""
Get reposition costs of cooling equipment per peak-load in currency/W
:return: float
"""
return self._cooling_equipment_reposition
@property
def cooling_equipment_initial_investment(self):
"""
Get initial investment costs of cooling equipment per peak-load in currency/W
:return: float
"""
return self._cooling_equipment_initial_investment
@property
def cooling_equipment_lifetime(self):
"""
Get lifetime of cooling equipment in years
:return: float
"""
return self._cooling_equipment_lifetime
@property
def general_hvac_equipment_reposition(self):
"""
Get reposition costs of general hvac equipment per peak-air-flow in currency/(m3/s)
:return: float
"""
return self._general_hvac_equipment_reposition
@property
def general_hvac_equipment_initial_investment(self):
"""
Get initial investment costs of cooling equipment per peak-air-flow in currency/(m3/s)
:return: float
"""
return self._general_hvac_equipment_initial_investment
@property
def general_hvac_equipment_lifetime(self):
"""
Get lifetime of cooling equipment in years
:return: float
"""
return self._general_hvac_equipment_lifetime

View File

@ -1,64 +1,62 @@
"""
Income from costs catalog
Incomes included in the costs catalog
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union
class Income:
def __init__(self, construction, hvac, photovoltaic_system, electricity_exports, heat_exports, co2):
self._construction = construction
self._hvac = hvac
self._photovoltaic_system = photovoltaic_system
self._electricity_exports = electricity_exports
self._heat_exports = heat_exports
self._co2 = co2
def __init__(self, construction_subsidy=None,
hvac_subsidy=None,
photovoltaic_subsidy=None,
electricity_export=None,
reductions_tax=None):
self._construction_subsidy = construction_subsidy
self._hvac_subsidy = hvac_subsidy
self._photovoltaic_subsidy = photovoltaic_subsidy
self._electricity_export = electricity_export
self._reductions_tax = reductions_tax
@property
def construction(self):
def construction_subsidy(self) -> Union[None, float]:
"""
Get construction subsidy in % of total investment construction cost
:return: float
Get subsidy for construction in percentage
:return: None or float
"""
return self._construction
return self._construction_subsidy
@property
def hvac(self):
def hvac_subsidy(self) -> Union[None, float]:
"""
Get hvac subsidy in % of total investment HVAC cost
:return: float
Get subsidy for HVAC system in percentage
:return: None or float
"""
return self._hvac
return self._hvac_subsidy
@property
def photovoltaic_system(self):
def photovoltaic_subsidy(self) -> Union[None, float]:
"""
Get photovoltaic system subsidy in % of total investment photovoltaic cost
:return: float
Get subsidy PV systems in percentage
:return: None or float
"""
return self._photovoltaic_system
return self._photovoltaic_subsidy
@property
def electricity_exports(self):
def electricity_export(self) -> Union[None, float]:
"""
Get electricity exports gains in currency/J
:return: float
Get electricity export incomes in currency per J
:return: None or float
"""
return self._construction
return self._construction_subsidy
@property
def heat_exports(self):
def reductions_tax(self) -> Union[None, float]:
"""
Get heat exports gains in currency/J
:return: float
Get reduction in taxes in percentage (-)
:return: None or float
"""
return self._heat_exports
@property
def co2(self):
"""
Get co2 income in currency/kg
:return: float
"""
return self._co2
return self._reductions_tax

View File

@ -0,0 +1,68 @@
"""
Cost item properties
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union
class ItemDescription:
def __init__(self, item_type,
initial_investment=None,
initial_investment_unit=None,
refurbishment=None,
refurbishment_unit=None,
reposition=None,
reposition_unit=None,
lifetime=None):
self._item_type = item_type
self._initial_investment = initial_investment
self._initial_investment_unit = initial_investment_unit
self._refurbishment = refurbishment
self._refurbishment_unit = refurbishment_unit
self._reposition = reposition
self._reposition_unit = reposition_unit
self._lifetime = lifetime
@property
def type(self):
"""
Get item type
:return: str
"""
return self._item_type
@property
def initial_investment(self) -> Union[tuple[None, None], tuple[float, str]]:
"""
Get initial investment of the specific item in given units
:return: None, None or float, str
"""
return self._initial_investment, self._initial_investment_unit
@property
def refurbishment(self) -> Union[tuple[None, None], tuple[float, str]]:
"""
Get refurbishment costs of the specific item in given units
:return: None, None or float, str
"""
return self._refurbishment, self._refurbishment_unit
@property
def reposition(self) -> Union[tuple[None, None], tuple[float, str]]:
"""
Get reposition costs of the specific item in given units
:return: None, None or float, str
"""
return self._reposition, self._reposition_unit
@property
def lifetime(self) -> Union[None, float]:
"""
Get lifetime in years
:return: None or float
"""
return self._lifetime

View File

@ -1,104 +1,58 @@
"""
Cost catalog OperationalCost
Operational costs included in the catalog
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import List
from hub.catalog_factories.data_models.cost.fuel import Fuel
class OperationalCost:
def __init__(self, fuel_type, fuel_fixed_operational_monthly, fuel_fixed_operational_peak,
fuel_variable_operational, heating_equipment_maintenance, cooling_equipment_maintenance,
general_hvac_equipment_maintenance, photovoltaic_system_maintenance, other_systems_maintenance,
co2_emissions):
self._fuel_type = fuel_type
self._fuel_fixed_operational_monthly = fuel_fixed_operational_monthly
self._fuel_fixed_operational_peak = fuel_fixed_operational_peak
self._fuel_variable_operational = fuel_variable_operational
self._heating_equipment_maintenance = heating_equipment_maintenance
self._cooling_equipment_maintenance = cooling_equipment_maintenance
self._general_hvac_equipment_maintenance = general_hvac_equipment_maintenance
self._photovoltaic_system_maintenance = photovoltaic_system_maintenance
self._other_systems_maintenance = other_systems_maintenance
self._co2_emissions = co2_emissions
def __init__(self, fuels, maintenance_heating, maintenance_cooling, maintenance_pv, co2):
self._fuels = fuels
self._maintenance_heating = maintenance_heating
self._maintenance_cooling = maintenance_cooling
self._maintenance_pv = maintenance_pv
self._co2 = co2
@property
def fuel_type(self):
def fuels(self) -> List[Fuel]:
"""
Get fuel type
:return: string
Get fuels listed in capital costs
:return: [FUEL]
"""
return self._fuel_type
return self._fuels
@property
def fuel_fixed_operational_monthly(self):
def maintenance_heating(self):
"""
Get fuel fixed operational cost in currency/month
Get cost of maintaining the heating system in currency/W
:return: float
"""
return self._fuel_fixed_operational_monthly
return self._maintenance_heating
@property
def fuel_fixed_operational_peak(self):
def maintenance_cooling(self):
"""
Get fuel fixed operational cost per peak power in currency/W
Get cost of maintaining the cooling system in currency/W
:return: float
"""
return self._fuel_fixed_operational_peak
return self._maintenance_cooling
@property
def fuel_variable_operational(self):
def maintenance_pv(self):
"""
Get fuel variable operational cost in currency/J
Get cost of maintaining the PV system in currency/m2
:return: float
"""
return self._fuel_variable_operational
return self._maintenance_pv
@property
def heating_equipment_maintenance(self):
def co2(self):
"""
Get heating equipment maintenance cost per peak power in currency/W
Get cost of CO2 emissions in currency/kgCO2
:return: float
"""
return self._heating_equipment_maintenance
@property
def cooling_equipment_maintenance(self):
"""
Get cooling equipment maintenance cost per peak power in currency/W
:return: float
"""
return self._cooling_equipment_maintenance
@property
def general_hvac_equipment_maintenance(self):
"""
Get general hvac equipment maintenance cost per peak-air-flow in currency/(m3/s)
:return: float
"""
return self._general_hvac_equipment_maintenance
@property
def photovoltaic_system_maintenance(self):
"""
Get photovoltaic system maintenance cost per panels area in currency/m2
:return: float
"""
return self._photovoltaic_system_maintenance
@property
def other_systems_maintenance(self):
"""
Get other systems' maintenance cost per building's foot-print area in currency/m2
:return: float
"""
return self._other_systems_maintenance
@property
def co2_emissions(self):
"""
Get CO2 emissions cost in currency/kg
:return: float
"""
return self._co2_emissions
return self._co2

View File

@ -1,106 +0,0 @@
"""
Systems cost catalog
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from hub.catalog_factories.data_models.cost.hvac import Hvac
class Systems:
def __init__(self, hvac, photovoltaic_system_reposition, photovoltaic_system_initial_investment,
photovoltaic_system_lifetime, other_conditioning_systems_reposition,
other_conditioning_systems_initial_investment, other_conditioning_systems_lifetime,
lighting_reposition, lighting_initial_investment, lighting_lifetime):
self._hvac = hvac
self._photovoltaic_system_reposition = photovoltaic_system_reposition
self._photovoltaic_system_initial_investment = photovoltaic_system_initial_investment
self._photovoltaic_system_lifetime = photovoltaic_system_lifetime
self._other_conditioning_systems_reposition = other_conditioning_systems_reposition
self._other_conditioning_systems_initial_investment = other_conditioning_systems_initial_investment
self._other_conditioning_systems_lifetime = other_conditioning_systems_lifetime
self._lighting_reposition = lighting_reposition
self._lighting_initial_investment = lighting_initial_investment
self._lighting_lifetime = lighting_lifetime
@property
def hvac(self) -> Hvac:
"""
Get hvac capital cost
:return: Hvac
"""
return self._hvac
@property
def photovoltaic_system_reposition(self):
"""
Get photovoltaic system reposition cost per area of panels in currency/m2
:return: float
"""
return self._photovoltaic_system_reposition
@property
def photovoltaic_system_initial_investment(self):
"""
Get photovoltaic system initial investment per area of panels in currency/m2
:return: float
"""
return self._photovoltaic_system_initial_investment
@property
def photovoltaic_system_lifetime(self):
"""
Get photovoltaic system lifetime in years
:return: float
"""
return self._photovoltaic_system_lifetime
@property
def other_conditioning_systems_reposition(self):
"""
Get other conditioning systems reposition cost per building's foot-print area in currency/m2
:return: float
"""
return self._other_conditioning_systems_reposition
@property
def other_conditioning_systems_initial_investment(self):
"""
Get other conditioning systems initial investment per building's foot-print area in currency/m2
:return: float
"""
return self._other_conditioning_systems_initial_investment
@property
def other_conditioning_systems_lifetime(self):
"""
Get other conditioning systems lifetime in years
:return: float
"""
return self._other_conditioning_systems_lifetime
@property
def lighting_reposition(self):
"""
Get lighting reposition cost per building's foot-print area in currency/m2
:return: float
"""
return self._lighting_reposition
@property
def lighting_initial_investment(self):
"""
Get lighting initial investment per building's foot-print area in currency/m2
:return: float
"""
return self._lighting_initial_investment
@property
def lighting_lifetime(self):
"""
Get lighting lifetime in years
:return: float
"""
return self._lighting_lifetime

View File

@ -0,0 +1,54 @@
"""
Usage catalog domestic hot water
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union, List
from hub.catalog_factories.data_models.usages.schedule import Schedule
class DomesticHotWater:
"""
DomesticHotWater class
"""
def __init__(self, density, peak_flow, service_temperature, schedules):
self._density = density
self._peak_flow = peak_flow
self._service_temperature = service_temperature
self._schedules = schedules
@property
def density(self) -> Union[None, float]:
"""
Get domestic hot water load density in Watts per m2
:return: None or float
"""
return self._density
@property
def peak_flow(self) -> Union[None, float]:
"""
Get domestic hot water peak_flow density in m3 per second and m2
:return: None or float
"""
return self._peak_flow
@property
def service_temperature(self) -> Union[None, float]:
"""
Get service temperature in degrees Celsius
:return: None or float
"""
return self._service_temperature
@property
def schedules(self) -> Union[None, List[Schedule]]:
"""
Get schedules
dataType = fraction of loads
:return: None or [Schedule]
"""
return self._schedules

View File

@ -10,6 +10,7 @@ from hub.catalog_factories.data_models.usages.appliances import Appliances
from hub.catalog_factories.data_models.usages.lighting import Lighting
from hub.catalog_factories.data_models.usages.ocupancy import Occupancy
from hub.catalog_factories.data_models.usages.thermal_control import ThermalControl
from hub.catalog_factories.data_models.usages.domestic_hot_water import DomesticHotWater
class Usage:
@ -21,7 +22,8 @@ class Usage:
occupancy,
lighting,
appliances,
thermal_control):
thermal_control,
domestic_hot_water):
self._name = name
self._hours_day = hours_day
self._days_year = days_year
@ -32,6 +34,7 @@ class Usage:
self._lighting = lighting
self._appliances = appliances
self._thermal_control = thermal_control
self._domestic_hot_water = domestic_hot_water
@property
def name(self) -> Union[None, str]:
@ -108,7 +111,15 @@ class Usage:
@property
def thermal_control(self) -> Union[None, ThermalControl]:
"""
Get thermal control of this thermal zone
Get thermal control information
:return: None or ThermalControl
"""
return self._thermal_control
@property
def domestic_hot_water(self) -> Union[None, DomesticHotWater]:
"""
Get domestic hot water information
:return: None or DomesticHotWater
"""
return self._domestic_hot_water

View File

@ -0,0 +1,189 @@
"""
NRCAN energy systems catalog
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 json
import urllib.request
import xmltodict
import hub.helpers.constants as cte
from hub.catalog_factories.catalog import Catalog
from hub.catalog_factories.data_models.usages.appliances import Appliances
from hub.catalog_factories.data_models.usages.content import Content
from hub.catalog_factories.data_models.usages.lighting import Lighting
from hub.catalog_factories.data_models.usages.ocupancy import Occupancy
from hub.catalog_factories.data_models.usages.schedule import Schedule
from hub.catalog_factories.data_models.usages.thermal_control import ThermalControl
from hub.catalog_factories.data_models.usages.usage import Usage
from hub.catalog_factories.usage.usage_helper import UsageHelper
class NrcanCatalog(Catalog):
def __init__(self, path):
path = str(path / 'nrcan.xml')
self._content = None
self._schedules = {}
with open(path) as xml:
self._metadata = xmltodict.parse(xml.read())
self._base_url = self._metadata['nrcan']['@base_url']
self._load_schedules()
self._content = Content(self._load_archetypes())
def _load_archetypes(self):
usages = []
name = self._metadata['nrcan']
url = f'{self._base_url}{name["space_types_location"]}'
with urllib.request.urlopen(url) as json_file:
space_types = json.load(json_file)['tables']['space_types']['table']
# space_types = [st for st in space_types if st['building_type'] == 'Space Function']
space_types = [st for st in space_types if st['space_type'] == 'WholeBuilding']
for space_type in space_types:
# usage_type = space_type['space_type']
usage_type = space_type['building_type']
occupancy_schedule_name = space_type['occupancy_schedule']
lighting_schedule_name = space_type['lighting_schedule']
appliance_schedule_name = space_type['electric_equipment_schedule']
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']
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)
appliance_schedule = self._get_schedules(appliance_schedule_name)
heating_schedule = self._get_schedules(heating_setpoint_schedule_name)
cooling_schedule = self._get_schedules(cooling_setpoint_schedule_name)
hvac_availability = self._get_schedules(hvac_schedule_name)
occupancy_density = space_type['occupancy_per_area']
# ACH
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'] / occupancy_density\
/ (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
# W/sqft to W/m2
lighting_density = space_type['lighting_per_area'] * cte.METERS_TO_FEET * cte.METERS_TO_FEET
lighting_radiative_fraction = space_type['lighting_fraction_radiant']
lighting_convective_fraction = 0
if lighting_radiative_fraction is not None:
lighting_convective_fraction = 1 - lighting_radiative_fraction
lighting_latent_fraction = 0
# W/sqft to W/m2
appliances_density = space_type['electric_equipment_per_area'] * cte.METERS_TO_FEET * cte.METERS_TO_FEET
appliances_radiative_fraction = space_type['electric_equipment_fraction_radiant']
appliances_latent_fraction = space_type['electric_equipment_fraction_latent']
appliances_convective_fraction = 0
if appliances_radiative_fraction is not None and appliances_latent_fraction is not None:
appliances_convective_fraction = 1 - appliances_radiative_fraction - appliances_latent_fraction
occupancy = Occupancy(occupancy_density,
None,
None,
None,
occupancy_schedule)
lighting = Lighting(lighting_density,
lighting_convective_fraction,
lighting_radiative_fraction,
lighting_latent_fraction,
lighting_schedule)
appliances = Appliances(appliances_density,
appliances_convective_fraction,
appliances_radiative_fraction,
appliances_latent_fraction,
appliance_schedule)
thermal_control = ThermalControl(None,
None,
None,
hvac_availability,
heating_schedule,
cooling_schedule)
hours_day = None
days_year = None
usages.append(Usage(usage_type,
hours_day,
days_year,
mechanical_air_change,
ventilation_rate,
occupancy,
lighting,
appliances,
thermal_control))
return usages
def names(self, category=None):
"""
Get the catalog elements names
:parm: optional category filter
"""
if category is None:
_names = {'archetypes': [], 'constructions': [], 'materials': [], 'windows': []}
for archetype in self._content.archetypes:
_names['archetypes'].append(archetype.name)
for construction in self._content.constructions:
_names['constructions'].append(construction.name)
for material in self._content.materials:
_names['materials'].append(material.name)
for window in self._content.windows:
_names['windows'].append(window.name)
else:
_names = {category: []}
if category.lower() == 'archetypes':
for archetype in self._content.archetypes:
_names[category].append(archetype.name)
elif category.lower() == 'constructions':
for construction in self._content.constructions:
_names[category].append(construction.name)
elif category.lower() == 'materials':
for material in self._content.materials:
_names[category].append(material.name)
elif category.lower() == 'windows':
for window in self._content.windows:
_names[category].append(window.name)
else:
raise ValueError(f'Unknown category [{category}]')
def entries(self, category=None):
"""
Get the catalog elements
:parm: optional category filter
"""
if category is None:
return self._content
else:
if category.lower() == 'archetypes':
return self._content.archetypes
elif category.lower() == 'constructions':
return self._content.constructions
elif category.lower() == 'materials':
return self._content.materials
elif category.lower() == 'windows':
return self._content.windows
else:
raise ValueError(f'Unknown category [{category}]')
def get_entry(self, name):
"""
Get one catalog element by names
:parm: entry name
"""
for entry in self._content.archetypes:
if entry.name.lower() == name.lower():
return entry
for entry in self._content.constructions:
if entry.name.lower() == name.lower():
return entry
for entry in self._content.materials:
if entry.name.lower() == name.lower():
return entry
for entry in self._content.windows:
if entry.name.lower() == name.lower():
return entry
raise IndexError(f"{name} doesn't exists in the catalog")

View File

@ -0,0 +1,42 @@
"""
Usage catalog factory, publish the usage information
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from pathlib import Path
from typing import TypeVar
from hub.catalog_factories.energy_systems.nrcan_catalog import NrcanCatalog
from hub.hub_logger import logger
from hub.helpers.utils import validate_import_export_type
Catalog = TypeVar('Catalog')
class UsageCatalogFactory:
def __init__(self, file_type, base_path=None):
if base_path is None:
base_path = Path(Path(__file__).parent.parent / 'data/energy_systems')
self._catalog_type = '_' + file_type.lower()
class_funcs = validate_import_export_type(UsageCatalogFactory)
if self._catalog_type not in class_funcs:
err_msg = f"Wrong import type. Valid functions include {class_funcs}"
logger.error(err_msg)
raise Exception(err_msg)
self._path = base_path
@property
def _nrcan(self):
"""
Retrieve NRCAN catalog
"""
# nrcan retrieves the data directly from github
return NrcanCatalog(self._path)
@property
def catalog(self) -> Catalog:
"""
Enrich the city given to the class using the class given handler
:return: Catalog
"""
return getattr(self, self._catalog_type, lambda: None)

View File

@ -14,6 +14,7 @@ from hub.catalog_factories.data_models.usages.appliances import Appliances
from hub.catalog_factories.data_models.usages.content import Content
from hub.catalog_factories.data_models.usages.lighting import Lighting
from hub.catalog_factories.data_models.usages.ocupancy import Occupancy
from hub.catalog_factories.data_models.usages.domestic_hot_water import DomesticHotWater
from hub.catalog_factories.data_models.usages.schedule import Schedule
from hub.catalog_factories.data_models.usages.thermal_control import ThermalControl
from hub.catalog_factories.data_models.usages.usage import Usage
@ -51,6 +52,7 @@ class ComnetCatalog(Catalog):
ventilation_rate = self._archetypes['ventilation rate'][comnet_usage]
# convert cfm/ft2 to m3/m2.s
ventilation_rate = ventilation_rate / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
domestic_hot_water_archetype = self._archetypes['water heating'][comnet_usage]
# get occupancy
occupancy_density = occupancy_archetype[0] / pow(cte.METERS_TO_FEET, 2)
@ -96,6 +98,16 @@ class ComnetCatalog(Catalog):
self._schedules[schedule_name]['ClgSetPt']
)
# get domestic hot water
density = domestic_hot_water_archetype
# convert Btu/h/occ to W/m2
density = float(density) * cte.BTU_H_TO_WATTS * occupancy_density
domestic_hot_water_service_temperature = self._schedules[schedule_name]['WtrHtrSetPt'][0].values[0]
domestic_hot_water = DomesticHotWater(density,
None,
domestic_hot_water_service_temperature,
self._schedules[schedule_name]['Service Hot Water']
)
usages.append(Usage(comnet_usage,
hours_day,
days_year,
@ -104,7 +116,8 @@ class ComnetCatalog(Catalog):
occupancy,
lighting,
appliances,
thermal_control))
thermal_control,
domestic_hot_water))
self._content = Content(usages)
@ -136,7 +149,7 @@ class ComnetCatalog(Catalog):
_schedule_values[day] = _extracted_data.iloc[start:end, 3:27].to_numpy().tolist()[0]
_schedule = []
for day in _schedule_values:
if schedule_name == 'ClgSetPt' or schedule_name == 'HtgSetPt':
if schedule_name == 'ClgSetPt' or schedule_name == 'HtgSetPt' or schedule_name == 'WtrHtrSetPt':
# to celsius
if 'n.a.' in _schedule_values[day]:
_schedule_values[day] = None

View File

@ -16,6 +16,7 @@ from hub.catalog_factories.data_models.usages.appliances import Appliances
from hub.catalog_factories.data_models.usages.content import Content
from hub.catalog_factories.data_models.usages.lighting import Lighting
from hub.catalog_factories.data_models.usages.ocupancy import Occupancy
from hub.catalog_factories.data_models.usages.domestic_hot_water import DomesticHotWater
from hub.catalog_factories.data_models.usages.schedule import Schedule
from hub.catalog_factories.data_models.usages.thermal_control import ThermalControl
from hub.catalog_factories.data_models.usages.usage import Usage
@ -36,7 +37,7 @@ class NrcanCatalog(Catalog):
@staticmethod
def _extract_schedule(raw):
nrcan_schedule_type = raw['category']
if 'Heating' in raw['name']:
if 'Heating' in raw['name'] and 'Water' not in raw['name']:
nrcan_schedule_type = f'{nrcan_schedule_type} Heating'
elif 'Cooling' in raw['name']:
nrcan_schedule_type = f'{nrcan_schedule_type} Cooling'
@ -45,8 +46,8 @@ class NrcanCatalog(Catalog):
hub_type = UsageHelper().nrcan_schedule_type_to_hub_schedule_type[nrcan_schedule_type]
data_type = UsageHelper().nrcan_data_type_to_hub_data_type[raw['units']]
time_step = UsageHelper().nrcan_time_to_hub_time[raw['type']]
# nrcan only uses yearly range for the schedules
time_range = cte.YEAR
# nrcan only uses daily range for the schedules
time_range = cte.DAY
day_types = UsageHelper().nrcan_day_type_to_hub_days[raw['day_types']]
return Schedule(hub_type, raw['values'], data_type, time_step, time_range, day_types)
@ -78,10 +79,8 @@ class NrcanCatalog(Catalog):
url = f'{self._base_url}{name["space_types_location"]}'
with urllib.request.urlopen(url) as json_file:
space_types = json.load(json_file)['tables']['space_types']['table']
# space_types = [st for st in space_types if st['building_type'] == 'Space Function']
space_types = [st for st in space_types if st['space_type'] == 'WholeBuilding']
for space_type in space_types:
# usage_type = space_type['space_type']
usage_type = space_type['building_type']
occupancy_schedule_name = space_type['occupancy_schedule']
lighting_schedule_name = space_type['lighting_schedule']
@ -91,12 +90,14 @@ class NrcanCatalog(Catalog):
hvac_schedule_name = hvac_schedule_name.replace('FAN', 'Fan')
heating_setpoint_schedule_name = space_type['heating_setpoint_schedule']
cooling_setpoint_schedule_name = space_type['cooling_setpoint_schedule']
domestic_hot_water_schedule_name = space_type['service_water_heating_schedule']
occupancy_schedule = self._get_schedules(occupancy_schedule_name)
lighting_schedule = self._get_schedules(lighting_schedule_name)
appliance_schedule = self._get_schedules(appliance_schedule_name)
heating_schedule = self._get_schedules(heating_setpoint_schedule_name)
cooling_schedule = self._get_schedules(cooling_setpoint_schedule_name)
hvac_availability = self._get_schedules(hvac_schedule_name)
domestic_hot_water_load_schedule = self._get_schedules(domestic_hot_water_schedule_name)
occupancy_density = space_type['occupancy_per_area']
@ -124,6 +125,11 @@ class NrcanCatalog(Catalog):
if appliances_radiative_fraction is not None and appliances_latent_fraction is not None:
appliances_convective_fraction = 1 - appliances_radiative_fraction - appliances_latent_fraction
# peak flow in gallons/h/ft2
domestic_hot_water_peak_flow = space_type['service_water_heating_peak_flow_per_area'] \
* cte.GALLONS_TO_QUBIC_METERS / cte.HOUR_TO_SECONDS * pow(cte.METERS_TO_FEET, 2)
domestic_hot_water_service_temperature = space_type['service_water_heating_target_temperature']
occupancy = Occupancy(occupancy_density,
None,
None,
@ -145,6 +151,11 @@ class NrcanCatalog(Catalog):
hvac_availability,
heating_schedule,
cooling_schedule)
domestic_hot_water = DomesticHotWater(None,
domestic_hot_water_peak_flow,
domestic_hot_water_service_temperature,
domestic_hot_water_load_schedule)
hours_day = None
days_year = None
usages.append(Usage(usage_type,
@ -155,7 +166,8 @@ class NrcanCatalog(Catalog):
occupancy,
lighting,
appliances,
thermal_control))
thermal_control,
domestic_hot_water))
return usages
def names(self, category=None):

View File

@ -19,7 +19,8 @@ class UsageHelper:
'Equipment': cte.APPLIANCES,
'Thermostat Setpoint Cooling': cte.COOLING_SET_POINT, # Compose 'Thermostat Setpoint' + 'Cooling'
'Thermostat Setpoint Heating': cte.HEATING_SET_POINT, # Compose 'Thermostat Setpoint' + 'Heating'
'Fan': cte.HVAC_AVAILABILITY
'Fan': cte.HVAC_AVAILABILITY,
'Service Water Heating': cte.DOMESTIC_HOT_WATER
}
_nrcan_data_type_to_hub_data_type = {
'FRACTION': cte.FRACTION,

View File

@ -152,6 +152,10 @@ class Polygon:
self._area += np.linalg.norm(np.cross(ab, ac)) / 2
return self._area
@area.setter
def area(self, value):
self._area = value
@property
def normal(self) -> np.ndarray:
"""

View File

@ -38,6 +38,7 @@ class Building(CityObject):
self._shell = None
self._alias = None
self._type = 'building'
self._cold_water_temperature = dict()
self._heating = dict()
self._cooling = dict()
self._lighting_electrical_demand = dict()
@ -265,6 +266,22 @@ class Building(CityObject):
if value is not None:
self._storeys_above_ground = int(value)
@property
def cold_water_temperature(self) -> {float}:
"""
Get cold water temperature in degrees Celsius
:return: dict{DataFrame(float)}
"""
return self._cold_water_temperature
@cold_water_temperature.setter
def cold_water_temperature(self, value):
"""
Set cold water temperature in degrees Celsius
:param value: dict{DataFrame(float)}
"""
self._cold_water_temperature = value
@property
def heating(self) -> dict:
"""

View File

@ -0,0 +1,87 @@
"""
Domestic Hot Water module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2023 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union, List
from hub.city_model_structure.attributes.schedule import Schedule
class DomesticHotWater:
"""
DomesticHotWater class
"""
def __init__(self):
self._density = None
self._peak_flow = None
self._service_temperature = None
self._schedules = None
@property
def density(self) -> Union[None, float]:
"""
Get domestic hot water load density in Watts per m2
:return: None or float
"""
return self._density
@density.setter
def density(self, value):
"""
Set domestic hot water load density in Watts per m2
:param value: float
"""
if value is not None:
self._density = float(value)
@property
def peak_flow(self) -> Union[None, float]:
"""
Get domestic hot water peak_flow density in m3 per second and m2
:return: None or float
"""
return self._peak_flow
@peak_flow.setter
def peak_flow(self, value):
"""
Set domestic hot water peak_flow density in m3 per second and m2
:return: None or float
"""
self._peak_flow = value
@property
def service_temperature(self) -> Union[None, float]:
"""
Get service temperature in degrees Celsius
:return: None or float
"""
return self._service_temperature
@service_temperature.setter
def service_temperature(self, value):
"""
Set service temperature in degrees Celsius
:param value: float
"""
if value is not None:
self._service_temperature = float(value)
@property
def schedules(self) -> Union[None, List[Schedule]]:
"""
Get schedules
dataType = fraction
:return: None or [Schedule]
"""
return self._schedules
@schedules.setter
def schedules(self, value):
"""
Set schedules
dataType = fraction
:param value: [Schedule]
"""
self._schedules = value

View File

@ -15,6 +15,7 @@ from hub.city_model_structure.building_demand.appliances import Appliances
from hub.city_model_structure.building_demand.lighting import Lighting
from hub.city_model_structure.building_demand.internal_gain import InternalGain
from hub.city_model_structure.building_demand.thermal_control import ThermalControl
from hub.city_model_structure.building_demand.domestic_hot_water import DomesticHotWater
from hub.city_model_structure.attributes.schedule import Schedule
import hub.helpers.constants as cte
@ -53,6 +54,7 @@ class ThermalZone:
self._appliances = None
self._internal_gains = None
self._thermal_control = None
self._domestic_hot_water = None
self._usages = None
@property
@ -590,6 +592,46 @@ class ThermalZone:
return self._thermal_control
@property
def domestic_hot_water(self) -> Union[None, DomesticHotWater]:
"""
Get domestic hot water information of this thermal zone
:return: None or DomesticHotWater
"""
self._domestic_hot_water = DomesticHotWater()
_mean_peak_density_load = 0
_mean_peak_flow = 0
_mean_service_temperature = 0
for usage in self.usages:
_mean_peak_density_load += usage.percentage * usage.domestic_hot_water.density
_mean_peak_flow += usage.percentage * usage.domestic_hot_water.peak_flow
_mean_service_temperature += usage.percentage * usage.domestic_hot_water.service_temperature
self._domestic_hot_water.density = _mean_peak_density_load
self._domestic_hot_water.peak_flow = _mean_peak_flow
self._domestic_hot_water.service_temperature = _mean_service_temperature
_domestic_hot_water_reference = self.usages[0].domestic_hot_water
if _domestic_hot_water_reference.schedules is not None:
_schedules = []
for i_schedule in range(0, len(_domestic_hot_water_reference.schedules)):
schedule = Schedule()
schedule.type = _domestic_hot_water_reference.schedules[i_schedule].type
schedule.day_types = _domestic_hot_water_reference.schedules[i_schedule].day_types
schedule.data_type = _domestic_hot_water_reference.schedules[i_schedule].data_type
schedule.time_step = _domestic_hot_water_reference.schedules[i_schedule].time_step
schedule.time_range = _domestic_hot_water_reference.schedules[i_schedule].time_range
new_values = []
for i_value in range(0, len(_domestic_hot_water_reference.schedules[i_schedule].values)):
_new_value = 0
for usage in self.usages:
_new_value += usage.percentage * usage.domestic_hot_water.schedules[i_schedule].values[i_value]
new_values.append(_new_value)
schedule.values = new_values
_schedules.append(schedule)
self._domestic_hot_water.schedules = _schedules
return self._domestic_hot_water
@property
def total_floor_area(self):
"""

View File

@ -12,6 +12,7 @@ from hub.city_model_structure.building_demand.occupancy import Occupancy
from hub.city_model_structure.building_demand.lighting import Lighting
from hub.city_model_structure.building_demand.appliances import Appliances
from hub.city_model_structure.building_demand.thermal_control import ThermalControl
from hub.city_model_structure.building_demand.domestic_hot_water import DomesticHotWater
from hub.city_model_structure.building_demand.internal_gain import InternalGain
@ -31,6 +32,7 @@ class Usage:
self._lighting = None
self._appliances = None
self._thermal_control = None
self._domestic_hot_water = None
@property
def id(self):
@ -236,7 +238,7 @@ class Usage:
@property
def thermal_control(self) -> Union[None, ThermalControl]:
"""
Get thermal control of this thermal zone
Get thermal control information
:return: None or ThermalControl
"""
return self._thermal_control
@ -244,7 +246,23 @@ class Usage:
@thermal_control.setter
def thermal_control(self, value):
"""
Set thermal control for this thermal zone
Set thermal control information
:param value: ThermalControl
"""
self._thermal_control = value
@property
def domestic_hot_water(self) -> Union[None, DomesticHotWater]:
"""
Get domestic hot water information
:return: None or ThermalControl
"""
return self._domestic_hot_water
@domestic_hot_water.setter
def domestic_hot_water(self, value):
"""
Set domestic hot water information
:return: None or ThermalControl
"""
self._domestic_hot_water = value

View File

@ -1,250 +0,0 @@
"""
UsageZone module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import uuid
from typing import Union, List
import hub.helpers.constants as cte
from hub.city_model_structure.building_demand.occupancy import Occupancy
from hub.city_model_structure.building_demand.lighting import Lighting
from hub.city_model_structure.building_demand.appliances import Appliances
from hub.city_model_structure.building_demand.thermal_control import ThermalControl
from hub.city_model_structure.building_demand.internal_gain import InternalGain
class UsageZone:
"""
UsageZone class
"""
def __init__(self):
self._id = None
self._usage = None
self._percentage = None
self._internal_gains = None
self._hours_day = None
self._days_year = None
self._mechanical_air_change = None
self._occupancy = None
self._lighting = None
self._appliances = None
self._thermal_control = None
@property
def id(self):
"""
Get usage zone id, a universally unique identifier randomly generated
:return: str
"""
if self._id is None:
self._id = uuid.uuid4()
return self._id
@property
def usage(self) -> Union[None, str]:
"""
Get usage zone usage
:return: None or str
"""
return self._usage
@usage.setter
def usage(self, value):
"""
Set usage zone usage
:param value: str
"""
if value is not None:
self._usage = str(value)
@property
def percentage(self):
"""
Get usage zone percentage in range[0,1]
:return: float
"""
return self._percentage
@percentage.setter
def percentage(self, value):
"""
Set usage zone percentage in range[0,1]
:param value: float
"""
if value is not None:
self._percentage = float(value)
@property
def internal_gains(self) -> List[InternalGain]:
"""
Calculates and returns the list of all internal gains defined
:return: InternalGains
"""
if self._internal_gains is None:
if self.occupancy is not None:
if self.occupancy.latent_internal_gain is not None:
_internal_gain = InternalGain()
_internal_gain.type = cte.OCCUPANCY
_total_heat_gain = (self.occupancy.sensible_convective_internal_gain
+ self.occupancy.sensible_radiative_internal_gain
+ self.occupancy.latent_internal_gain)
_internal_gain.average_internal_gain = _total_heat_gain
_internal_gain.latent_fraction = 0
_internal_gain.radiative_fraction = 0
_internal_gain.convective_fraction = 0
if _total_heat_gain != 0:
_internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain
_internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain
_internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain
_internal_gain.schedules = self.occupancy.occupancy_schedules
self._internal_gains = [_internal_gain]
if self.lighting is not None:
_internal_gain = InternalGain()
_internal_gain.type = cte.LIGHTING
_internal_gain.average_internal_gain = self.lighting.density
_internal_gain.latent_fraction = self.lighting.latent_fraction
_internal_gain.radiative_fraction = self.lighting.radiative_fraction
_internal_gain.convective_fraction = self.lighting.convective_fraction
_internal_gain.schedules = self.lighting.schedules
if self._internal_gains is not None:
self._internal_gains.append(_internal_gain)
else:
self._internal_gains = [_internal_gain]
if self.appliances is not None:
_internal_gain = InternalGain()
_internal_gain.type = cte.APPLIANCES
_internal_gain.average_internal_gain = self.appliances.density
_internal_gain.latent_fraction = self.appliances.latent_fraction
_internal_gain.radiative_fraction = self.appliances.radiative_fraction
_internal_gain.convective_fraction = self.appliances.convective_fraction
_internal_gain.schedules = self.appliances.schedules
if self._internal_gains is not None:
self._internal_gains.append(_internal_gain)
else:
self._internal_gains = [_internal_gain]
return self._internal_gains
@internal_gains.setter
def internal_gains(self, value):
"""
Set usage zone internal gains
:param value: [InternalGain]
"""
self._internal_gains = value
@property
def hours_day(self) -> Union[None, float]:
"""
Get usage zone usage hours per day
:return: None or float
"""
return self._hours_day
@hours_day.setter
def hours_day(self, value):
"""
Set usage zone usage hours per day
:param value: float
"""
if value is not None:
self._hours_day = float(value)
@property
def days_year(self) -> Union[None, float]:
"""
Get usage zone usage days per year
:return: None or float
"""
return self._days_year
@days_year.setter
def days_year(self, value):
"""
Set usage zone usage days per year
:param value: float
"""
if value is not None:
self._days_year = float(value)
@property
def mechanical_air_change(self) -> Union[None, float]:
"""
Get usage zone mechanical air change in air change per hour (ACH)
:return: None or float
"""
return self._mechanical_air_change
@mechanical_air_change.setter
def mechanical_air_change(self, value):
"""
Set usage zone mechanical air change in air change per hour (ACH)
:param value: float
"""
if value is not None:
self._mechanical_air_change = float(value)
@property
def occupancy(self) -> Union[None, Occupancy]:
"""
Get occupancy in the usage zone
:return: None or Occupancy
"""
return self._occupancy
@occupancy.setter
def occupancy(self, value):
"""
Set occupancy in the usage zone
:param value: Occupancy
"""
self._occupancy = value
@property
def lighting(self) -> Union[None, Lighting]:
"""
Get lighting information
:return: None or Lighting
"""
return self._lighting
@lighting.setter
def lighting(self, value):
"""
Set lighting information
:param value: Lighting
"""
self._lighting = value
@property
def appliances(self) -> Union[None, Appliances]:
"""
Get appliances information
:return: None or Appliances
"""
return self._appliances
@appliances.setter
def appliances(self, value):
"""
Set appliances information
:param value: Appliances
"""
self._appliances = value
@property
def thermal_control(self) -> Union[None, ThermalControl]:
"""
Get thermal control of this thermal zone
:return: None or ThermalControl
"""
return self._thermal_control
@thermal_control.setter
def thermal_control(self, value):
"""
Set thermal control for this thermal zone
:param value: ThermalControl
"""
self._thermal_control = value

View File

@ -459,6 +459,7 @@ class City:
for surface in city_object.surfaces:
radiation = surface.global_irradiance
if 'year' not in radiation and 'month' not in radiation:
continue
elif "year" in radiation:
building_radiation += radiation["year"].iloc[0]
@ -468,11 +469,11 @@ class City:
if building_radiation < min_radiation:
min_radiation = building_radiation
selected_city_object = city_object
# merge the city object with the minimum radiation
if selected_city_object is not None:
_merge_city.add_city_object(selected_city_object)
else:
_merge_city.add_city_object(building)
# merge the city object with the minimum radiation
if selected_city_object is not None:
_merge_city.add_city_object(selected_city_object)
else:
_merge_city.add_city_object(building)
return _merge_city
@property

View File

@ -34,7 +34,9 @@ class CityObject:
self._max_y = ConfigurationHelper().min_coordinate
self._max_z = ConfigurationHelper().min_coordinate
self._centroid = None
self._volume = None
self._external_temperature = dict()
self._ground_temperature = dict()
self._global_horizontal = dict()
self._diffuse = dict()
self._beam = dict()
@ -63,7 +65,13 @@ class CityObject:
Get city object volume in cubic meters
:return: float
"""
return self.simplified_polyhedron.volume
if self._volume is None:
self._volume = self.simplified_polyhedron.volume
return self._volume
@volume.setter
def volume(self, value):
self._volume = value
@property
def detailed_polyhedron(self) -> Polyhedron:
@ -158,6 +166,24 @@ class CityObject:
"""
self._external_temperature = value
# todo: this is the new format we will use to get rid of the data frames
@property
def ground_temperature(self) -> dict:
"""
Get ground temperature under the city object in Celsius at different depths in meters for different time steps
example of use: {month: {0.5: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]}}
:return: dict{dict{[float]}}
"""
return self._ground_temperature
@ground_temperature.setter
def ground_temperature(self, value):
"""
Set ground temperature under the city object in Celsius at different depths
:param value: dict{dict{[float]}}
"""
self._ground_temperature = value
@property
def global_horizontal(self) -> dict:
"""

View File

@ -1,6 +1,5 @@
# These values are intended as configurable assumptions
[buildings]
max_location_distance_for_shared_walls = 5.0
min_coordinate = -1.7976931348623157e+308
max_coordinate = 1.7976931348623157e+308
comnet_lighting_latent = 0
@ -18,3 +17,7 @@ convective_heat_transfer_coefficient_exterior = 20
soil_conductivity = 3
#m
soil_thickness = 0.5
short_wave_reflectance = 0.3
#C
cold_water_temperature = 10

View File

@ -1,89 +1,204 @@
<archetypes>
<archetype function="residential" municipality="montreal" currency="CAD">
<archetype function="residential" municipality="montreal" country="CA" lod="1">
<currency>CAD</currency>
<capital_cost>
<structural cost_unit="currency/m3"> 56 </structural>
<sub_structural cost_unit="currency/m2"> 9.8 </sub_structural>
<envelope>
<opaque>
<reposition cost_unit="currency/m2"> 43.4 </reposition>
<initial_investment cost_unit="currency/m2"> 36 </initial_investment>
<lifetime_equipment lifetime="years"> 50 </lifetime_equipment>
</opaque>
<transparent>
<reposition cost_unit="currency/m2"> 78 </reposition>
<initial_investment cost_unit="currency/m2"> 984.5 </initial_investment>
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
</transparent>
</envelope>
<systems>
<hvac>
<heating_equipment_cost>
<initial_investment cost_unit="currency/kW"> 363.5 </initial_investment>
<reposition cost_unit="currency/kW"> 363.5 </reposition>
<B_shell>
<B10_superstructure>
<refurbishment_cost_basement cost_unit="currency/m2"> 0 </refurbishment_cost_basement>
</B10_superstructure>
<B20_envelope>
<B2010_opaque_walls>
<refurbishment_cost cost_unit="currency/m2"> 304 </refurbishment_cost>
</B2010_opaque_walls>
<B2020_transparent>
<refurbishment_cost cost_unit="currency/m2"> 857.14 </refurbishment_cost>
</B2020_transparent>
</B20_envelope>
<B30_roofing>
<B3010_opaque_roof>
<refurbishment_cost cost_unit="currency/m2"> 118 </refurbishment_cost>
</B3010_opaque_roof>
</B30_roofing>
</B_shell>
<D_services>
<D30_hvac>
<D3010_energy_supply>
<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_energy_supply>
<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>
</heating_equipment_cost>
<cooling_equipment_cost>
<initial_investment cost_unit="currency/kW"> 363.5 </initial_investment>
<reposition cost_unit="currency/kW"> 363.5 </reposition>
</D3030_cooling_generation_systems>
<D3040_distribution_systems>
<investment_cost cost_unit="currency/kW"> 0 </investment_cost>
<reposition cost_unit="currency/kW"> 0 </reposition>
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
</cooling_equipment_cost>
<general_hvac_equipment_cost>
<initial_investment cost_unit="currency/(m3/h)"> 363.5 </initial_investment>
<reposition cost_unit="currency/(m3/h)"> 363.5 </reposition>
</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>
</general_hvac_equipment_cost>
</hvac>
<photovoltaic_system>
<initial_investment cost_unit="currency/m2"> 17 </initial_investment>
<reposition cost_unit="currency/m2"> 17 </reposition>
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
</photovoltaic_system>
<other_systems>
<initial_investment cost_unit="currency/m2"> 365 </initial_investment>
<reposition cost_unit="currency/m2"> 365 </reposition>
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
</other_systems>
<lighting>
<initial_investment cost_unit="currency/m2"> 365 </initial_investment>
<reposition cost_unit="currency/m2"> 365 </reposition>
<lifetime_equipment lifetime="years"> 15 </lifetime_equipment>
</lighting>
</systems>
<surface_finish cost_unit="currency/m2"> 88 </surface_finish>
<engineer cost_unit="%"> 2.5 </engineer>
</D3080_other_hvac_ahu>
</D30_hvac>
<D50_electrical>
<D5020lighting_and_branch_wiring>
<refurbishment_cost cost_unit="currency/kW"> 139 </refurbishment_cost>
<reposition cost_unit="currency/kW"> 139 </reposition>
<lifetime_equipment lifetime="years"> 20 </lifetime_equipment>
</D5020lighting_and_branch_wiring>
</D50_electrical>
</D_services>
<Z_allowances_overhead_profit>
<Z10_design_allowance cost_unit="%"> 2.5 </Z10_design_allowance>
<Z10_overhead_and_profit cost_unit="%"> 14 </Z10_overhead_and_profit>
</Z_allowances_overhead_profit>
</capital_cost>
<operational_cost>
<fuels>
<fuel fuel_type="electricity">
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
<fixed_power cost_unit="currency/month*kW"> 0 </fixed_power>
<variable cost_unit="currency/kWh"> 0.075 </variable>
</fuel>
<fuel fuel_type="gas">
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
<variable cost_unit="currency/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>
</fuels>
<maintenances>
<maintenance type="heating_equipment" cost_unit="currency/kW">40</maintenance>
<maintenance type="cooling_equipment" cost_unit="currency/kW">40</maintenance>
<maintenance type="photovoltaic_system" cost_unit="currency/m2">1</maintenance>
</maintenances>
<co2_cost cost_unit="currency/kgCO2"> 30 </co2_cost>
</operational_cost>
<end_of_life_cost cost_unit="currency/m2"> 6.3 </end_of_life_cost>
<incomes>
<subsidies>
<subsidy type="construction" cost_unit="%">2</subsidy>
<subsidy type="hvac" cost_unit="%">1.5</subsidy>
<subsidy type="photovoltaic" cost_unit="%">3.6</subsidy>
</subsidies>
<energy_exports>
<energy_export type="electricity" cost_unit="currency/kWh">0</energy_export>
</energy_exports>
<tax_reduction cost_unit="%">2</tax_reduction>
</incomes>
</archetype>
<archetype function="non-residential" municipality="montreal" country="CA" lod="1">
<currency>CAD</currency>
<capital_cost>
<B_shell>
<B10_superstructure>
<refurbishment_cost_basement cost_unit="currency/m2"> 0 </refurbishment_cost_basement>
</B10_superstructure>
<B20_envelope>
<B2010_opaque_walls>
<refurbishment_cost cost_unit="currency/m2"> 304 </refurbishment_cost>
</B2010_opaque_walls>
<B2020_transparent>
<refurbishment_cost cost_unit="currency/m2"> 857.14 </refurbishment_cost>
</B2020_transparent>
</B20_envelope>
<B30_roofing>
<B3010_opaque_roof>
<refurbishment_cost cost_unit="currency/m2"> 118 </refurbishment_cost>
</B3010_opaque_roof>
</B30_roofing>
</B_shell>
<D_services>
<D30_hvac>
<D3010_energy_supply>
<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_energy_supply>
<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_distribution_systems>
<refurbishment_cost cost_unit="currency/m2"> 0 </refurbishment_cost>
<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>
<refurbishment_cost cost_unit="currency/kW"> 139 </refurbishment_cost>
<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"> 0 </fixed_monthly>
<fixed_power cost_unit="currency/kW"> 0 </fixed_power>
</fixed>
<variable cost_unit="currency/kWh"> 5.6 </variable>
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
<fixed_power cost_unit="currency/(month*kW)"> 0 </fixed_power>
<variable cost_unit="currency/kWh"> 0.075 </variable>
</fuel>
<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>
<fuel fuel_type="gas">
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
<variable cost_unit="currency/m3"> 0.640 </variable>
</fuel>
<fuel fuel_type="diesel">
<variable cost_unit="currency/l"> 1.2 </variable>
</fuel>
<fuel fuel_type="biomass">
<variable cost_unit="currency/kg"> 0.09 </variable>
</fuel>
<maintenances>
<maintenance type="heating_equipment" cost_unit="currency/kW">40</maintenance>
<maintenance type="cooling_equipment" cost_unit="currency/kW">40</maintenance>
<maintenance type="photovoltaic_system" cost_unit="currency/m2">1</maintenance>
</maintenances>
<CO2_cost cost_unit="currency/kgCO2"> 30 </CO2_cost>
</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>
<subsidies>
<subsidy type="construction" cost_unit="%">2</subsidy>
<subsidy type="hvac" cost_unit="%">1.5</subsidy>
<subsidy type="photovoltaic" cost_unit="%">3.6</subsidy>
</subsidies>
<energy_exports>
<electricity cost_unit="currency/kWh"> 0 </electricity>
<heat cost_unit="currency/kWh"> 0 </heat>
<energy_export type="electricity" cost_unit="currency/kWh">0</energy_export>
</energy_exports>
<tax_reductions>
<reductions_taxes cost_unit="%"> 2 </reductions_taxes>
</tax_reductions>
<CO2_income cost_unit="currency/kgCO2exported"> 0 </CO2_income>
<tax_reduction cost_unit="%">2</tax_reduction>
</incomes>
</archetype>
</archetypes>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<nrcan base_url="https://raw.githubusercontent.com/NREL/openstudio-standards/master/lib/openstudio-standards/standards/necb/ECMS/data/">
<boilers_location>boiler_set.json</boilers_location>
<chillers_location>chiller_set.json</chillers_location>
<curves_location>curves.json</curves_location>
<furnaces_location>furnace_set.json </furnaces_location>
<heat_pumps_location>heat_pumps.json</heat_pumps_location>
<domestic_hot_water_systems_location>shw_set.json</domestic_hot_water_systems_location>
<pvs_location>pv.json</pvs_location>
<air_conditioners_location>unitary_acs.json</air_conditioners_location>
</nrcan>

View File

@ -7,6 +7,8 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
import numpy as np
from pathlib import Path
import sys
from hub.hub_logger import logger
from hub.exports.formats.insel import Insel
from hub.imports.weather.helpers.weather import Weather
@ -38,6 +40,10 @@ class InselMonthlyEnergyBalance(Insel):
if building.internal_zones is not None:
for internal_zone in building.internal_zones:
if internal_zone.thermal_zones is None:
logger.error(f'Building {building.name} has missing values. '
f'Monthly Energy Balance cannot be processed\n')
sys.stderr.write(f'Building {building.name} has missing values. '
f'Monthly Energy Balance cannot be processed\n')
break
self._contents.append(
self.generate_meb_template(building, output_path, self._radiation_calculation_method,self._weather_format)

View File

@ -4,6 +4,9 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project CoderPeter Yefi peteryefi@gmail.com
"""
import json
from typing import Union, Dict
from hub.persistence import City
from hub.persistence import Application
from hub.persistence import User
@ -23,23 +26,53 @@ class DBFactory:
self._city_object = CityObject(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
self._simulation_results = SimulationResults(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
def application_info(self, application_uuid):
def application_info(self, application_uuid) -> Union[Application, None]:
"""
Retrieve the application info for the given uuid
:param application_uuid: the uuid for the application
:return: Application or None
"""
return self._application.get_by_uuid(application_uuid)
def user_info(self, name, password, application_id):
"""
Retrieve the user info for the given name and password and application_id
:param name: the user name
:param password: the user password
:param application_id: the application id
:return: User or None
"""
return self._user.get_by_name_application_id_and_password(name, password, application_id)
def user_login(self, name, password, application_uuid):
"""
Retrieve the user info
:param name: the user name
:param password: the user password
:param application_uuid: the application uuid
:return: User or None
"""
return self._user.get_by_name_application_uuid_and_password(name, password, application_uuid)
def results(self, user_id, application_id, cities, result_names=[]):
def cities_by_user_and_application(self, user_id, application_id) -> [City]:
"""
Retrieve the cities belonging to the user and the application
:param user_id: User id
:param application_id: Application id
:return: [City]
"""
return self._city.get_by_user_id_and_application_id(user_id, application_id)
def building_info(self, name, city_id) -> Union[CityObject, None]:
"""
Retrieve the building info
:param name: Building name
:param city_id: City Id
:return: CityObject or None
"""
return self._city_object.get_by_name_and_city(name, city_id)
def results(self, user_id, application_id, cities, result_names=None) -> Dict:
"""
Retrieve the simulation results for the given cities
:param user_id: the user id owning the results
@ -47,16 +80,27 @@ class DBFactory:
:param cities: dictionary containing the city and building names for the results
:param result_names: if given, filter the results to the selected names
"""
results = []
for city in cities['cities'].keys():
city_id = self._city.get_by_user_id_application_id_and_name(user_id, application_id, city).id
for building_name in cities[city]:
if result_names is None:
result_names = []
results = {}
for city in cities['cities']:
city_name = next(iter(city))
result_set = self._city.get_by_user_id_application_id_and_name(user_id, application_id, city_name)
if result_set is None:
continue
city_id = result_set.id
results[city_name] = []
for building_name in city[city_name]:
if self._city_object.get_by_name_and_city(building_name, city_id) is None:
continue
city_object_id = self._city_object.get_by_name_and_city(building_name, city_id).id
results.append(self._simulation_results.get_simulation_results_by_city_id_city_object_id_and_names(
_ = self._simulation_results.get_simulation_results_by_city_id_city_object_id_and_names(
city_id,
city_object_id,
result_names))
result_names)
for value in _:
values = json.loads(value.values)
values["building"] = building_name
results[city_name].append(values)
return results

View File

@ -71,7 +71,7 @@ class ExportsFactory:
Export the city geometry to obj with grounded coordinates
:return: None
"""
return Obj(self._city, self._path).to_ground_points()
return Obj(self._city, self._path)
@property
def _sra(self):

View File

@ -11,24 +11,51 @@ from hub.exports.formats.triangular import Triangular
from hub.imports.geometry_factory import GeometryFactory
class Obj(Triangular):
class Obj:
"""
Export to obj format
"""
def __init__(self, city, path):
super().__init__(city, path, 'obj')
self._city = city
self._path = path
self._export()
def _to_vertex(self, coordinate):
x = coordinate[0] - self._city.lower_corner[0]
y = coordinate[1] - self._city.lower_corner[1]
z = coordinate[2] - self._city.lower_corner[2]
return f'v {x} {y} {z}\n'
def _export(self):
if self._city.name is None:
self._city.name = 'unknown_city'
file_name = self._city.name + '.obj'
file_path = (Path(self._path).resolve() / file_name).resolve()
vertices = {}
with open(file_path, 'w') as obj:
obj.write("# cerc-hub export\n")
vertex_index = 0
faces = []
for building in self._city.buildings:
obj.write(f'# building {building.name}\n')
for surface in building.surfaces:
obj.write(f'# surface {surface.name}\n')
face = 'f '
for coordinate in surface.perimeter_polygon.coordinates:
vertex = self._to_vertex(coordinate)
if vertex not in vertices.keys():
vertex_index += 1
vertices[vertex] = vertex_index
current = vertex_index
obj.write(vertex)
else:
current = vertices[vertex]
face = f'{face} {current}'
faces.append(f'{face} {face.split(" ")[1]}\n')
obj.writelines(faces)
faces = []
def to_ground_points(self):
"""
Move closer to the origin
"""
file_name_in = self._city.name + '.' + self._triangular_format
file_name_out = self._city.name + '_ground.' + self._triangular_format
file_path_in = (Path(self._path).resolve() / file_name_in).resolve()
file_path_out = (Path(self._path).resolve() / file_name_out).resolve()
obj = GeometryFactory('obj', path=file_path_in)
scene = obj.scene
scene.rezero()
obj_file = trimesh.exchange.obj.export_obj(scene)
with open(file_path_out, 'w') as file:
file.write(obj_file)

View File

@ -8,6 +8,7 @@ import xmltodict
from hub.imports.weather_factory import WeatherFactory
import hub.helpers.constants as cte
from hub.helpers.configuration_helper import ConfigurationHelper
class SimplifiedRadiosityAlgorithm:
@ -88,10 +89,15 @@ class SimplifiedRadiosityAlgorithm:
'@Simulate': f'{simulate}'
}
walls, roofs, floors = [], [], []
default_short_wave_reflectance = ConfigurationHelper().short_wave_reflectance
for surface in building.surfaces:
if surface.short_wave_reflectance is None:
short_wave_reflectance = default_short_wave_reflectance
else:
short_wave_reflectance = surface.short_wave_reflectance
surface_dict = {
'@id': f'{surface.id}',
'@ShortWaveReflectance': f'{surface.short_wave_reflectance}'
'@ShortWaveReflectance': f'{short_wave_reflectance}'
}
for point_index, point in enumerate(surface.perimeter_polygon.coordinates):
point = self._correct_point(point)

View File

@ -17,14 +17,6 @@ class ConfigurationHelper:
self._config = configparser.ConfigParser()
self._config.read(config_file)
@property
def max_location_distance_for_shared_walls(self) -> float:
"""
Get configured maximal distance between attributes to consider that they may share walls in meters
:return: 5.0
"""
return self._config.getfloat('buildings', 'max_location_distance_for_shared_walls')
@property
def min_coordinate(self) -> float:
"""
@ -138,3 +130,19 @@ class ConfigurationHelper:
:return: 0.5
"""
return self._config.getfloat('buildings', 'soil_thickness').real
@property
def short_wave_reflectance(self) -> float:
"""
Get configured short wave reflectance for surfaces that don't have construction assigned
:return: 0.3
"""
return self._config.getfloat('buildings', 'short_wave_reflectance').real
@property
def cold_water_temperature(self) -> float:
"""
Get configured cold water temperature in Celsius
:return: 10
"""
return self._config.getfloat('buildings', 'cold_water_temperature').real

View File

@ -8,13 +8,17 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
# universal constants
KELVIN = 273.15
WATER_DENSITY = 1000
WATER_HEAT_CAPACITY = 4182
# converters
HOUR_TO_MINUTES = 60
MINUTES_TO_SECONDS = 60
HOUR_TO_SECONDS = 3600
METERS_TO_FEET = 3.28084
BTU_H_TO_WATTS = 0.29307107
KILO_WATTS_HOUR_TO_JULES = 3600000
GALLONS_TO_QUBIC_METERS = 0.0037854117954011185
# time
SECOND = 'second'
@ -137,6 +141,7 @@ HEATING_SET_POINT = 'HtgSetPt'
EQUIPMENT = 'Equipment'
ACTIVITY = 'Activity'
PEOPLE_ACTIVITY_LEVEL = 'People Activity Level'
DOMESTIC_HOT_WATER = 'Domestic Hot Water'
# Geometry
EPSILON = 0.0000001
@ -157,3 +162,19 @@ MIN_FLOAT = float('-inf')
# Tools
SRA = 'sra'
INSEL_MEB = 'insel meb'
# Costs units
CURRENCY_PER_SQM = 'currency/m2'
CURRENCY_PER_CBM = 'currency/m3'
CURRENCY_PER_KW = 'currency/kW'
CURRENCY_PER_KWH = 'currency/kWh'
CURRENCY_PER_MONTH = 'currency/month'
CURRENCY_PER_LITRE = 'currency/l'
CURRENCY_PER_KG = 'currency/kg'
CURRENCY_PER_CBM_PER_HOUR = 'currency/(m3/h)'
PERCENTAGE = '%'
# Costs chapters
SUPERSTRUCTURE = 'B_shell'
ENVELOPE = 'D_services'
ALLOWANCES_OVERHEAD_PROFIT = 'Z_allowances_overhead_profit'

View File

@ -8,6 +8,7 @@ Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
import hub.helpers.constants as cte
class AlkisFunctionToHubFunction:
def __init__(self):

View File

@ -12,21 +12,21 @@ class HftFunctionToHubFunction:
def __init__(self):
self._dictionary = {
'residential': cte.RESIDENTIAL,
'single family house': cte.SINGLE_FAMILY_HOUSE,
'multifamily house': cte.MULTI_FAMILY_HOUSE,
'hotel': cte.HOTEL,
'hospital': cte.HOSPITAL,
'outpatient': cte.OUT_PATIENT_HEALTH_CARE,
'commercial': cte.SUPERMARKET,
'strip mall': cte.STRIP_MALL,
'warehouse': cte.WAREHOUSE,
'primary school': cte.PRIMARY_SCHOOL,
'secondary school': cte.EDUCATION,
'office': cte.MEDIUM_OFFICE,
'large office': cte.LARGE_OFFICE
}
'residential': cte.RESIDENTIAL,
'single family house': cte.SINGLE_FAMILY_HOUSE,
'multifamily house': cte.MULTI_FAMILY_HOUSE,
'hotel': cte.HOTEL,
'hospital': cte.HOSPITAL,
'outpatient': cte.OUT_PATIENT_HEALTH_CARE,
'commercial': cte.SUPERMARKET,
'strip mall': cte.STRIP_MALL,
'warehouse': cte.WAREHOUSE,
'primary school': cte.PRIMARY_SCHOOL,
'secondary school': cte.EDUCATION,
'office': cte.MEDIUM_OFFICE,
'large office': cte.LARGE_OFFICE
}
@property
def dictionary(self) -> dict:
def dictionary(self) -> dict:
return self._dictionary

View File

@ -12,66 +12,66 @@ class HubFunctionToNrcanConstructionFunction:
def __init__(self):
self._dictionary = {
cte.RESIDENTIAL: 'MidriseApartment',
cte.SINGLE_FAMILY_HOUSE: 'MidriseApartment',
cte.MULTI_FAMILY_HOUSE: 'HighriseApartment',
cte.ROW_HOUSE: 'MidriseApartment',
cte.MID_RISE_APARTMENT: 'MidriseApartment',
cte.HIGH_RISE_APARTMENT: 'HighriseApartment',
cte.OFFICE_AND_ADMINISTRATION: 'MediumOffice',
cte.SMALL_OFFICE: 'SmallOffice',
cte.MEDIUM_OFFICE: 'MediumOffice',
cte.LARGE_OFFICE: 'LargeOffice',
cte.COURTHOUSE: 'MediumOffice',
cte.FIRE_STATION: 'n/a',
cte.PENITENTIARY: 'LargeHotel',
cte.POLICE_STATION: 'n/a',
cte.POST_OFFICE: 'MediumOffice',
cte.LIBRARY: 'MediumOffice',
cte.EDUCATION: 'SecondarySchool',
cte.PRIMARY_SCHOOL: 'PrimarySchool',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'PrimarySchool',
cte.SECONDARY_SCHOOL: 'SecondarySchool',
cte.UNIVERSITY: 'SecondarySchool',
cte.LABORATORY_AND_RESEARCH_CENTER: 'SecondarySchool',
cte.STAND_ALONE_RETAIL: 'RetailStandalone',
cte.HOSPITAL: 'Hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'Outpatient',
cte.HEALTH_CARE: 'Outpatient',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'SmallHotel',
cte.COMMERCIAL: 'RetailStripmall',
cte.STRIP_MALL: 'RetailStripmall',
cte.SUPERMARKET: 'RetailStripmall',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'RetailStandalone',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'RetailStandalone',
cte.RESTAURANT: 'FullServiceRestaurant',
cte.QUICK_SERVICE_RESTAURANT: 'QuickServiceRestaurant',
cte.FULL_SERVICE_RESTAURANT: 'FullServiceRestaurant',
cte.HOTEL: 'SmallHotel',
cte.HOTEL_MEDIUM_CLASS: 'SmallHotel',
cte.SMALL_HOTEL: 'SmallHotel',
cte.LARGE_HOTEL: 'LargeHotel',
cte.DORMITORY: 'SmallHotel',
cte.EVENT_LOCATION: 'n/a',
cte.CONVENTION_CENTER: 'n/a',
cte.HALL: 'n/a',
cte.GREEN_HOUSE: 'n/a',
cte.INDUSTRY: 'n/a',
cte.WORKSHOP: 'n/a',
cte.WAREHOUSE: 'Warehouse',
cte.WAREHOUSE_REFRIGERATED: 'Warehouse',
cte.SPORTS_LOCATION: 'n/a',
cte.SPORTS_ARENA: 'n/a',
cte.GYMNASIUM: 'n/a',
cte.MOTION_PICTURE_THEATRE: 'n/a',
cte.MUSEUM: 'n/a',
cte.PERFORMING_ARTS_THEATRE: 'n/a',
cte.TRANSPORTATION: 'n/a',
cte.AUTOMOTIVE_FACILITY: 'n/a',
cte.PARKING_GARAGE: 'n/a',
cte.RELIGIOUS: 'n/a',
cte.NON_HEATED: 'n/a'
}
cte.RESIDENTIAL: 'MidriseApartment',
cte.SINGLE_FAMILY_HOUSE: 'MidriseApartment',
cte.MULTI_FAMILY_HOUSE: 'HighriseApartment',
cte.ROW_HOUSE: 'MidriseApartment',
cte.MID_RISE_APARTMENT: 'MidriseApartment',
cte.HIGH_RISE_APARTMENT: 'HighriseApartment',
cte.OFFICE_AND_ADMINISTRATION: 'MediumOffice',
cte.SMALL_OFFICE: 'SmallOffice',
cte.MEDIUM_OFFICE: 'MediumOffice',
cte.LARGE_OFFICE: 'LargeOffice',
cte.COURTHOUSE: 'MediumOffice',
cte.FIRE_STATION: 'n/a',
cte.PENITENTIARY: 'LargeHotel',
cte.POLICE_STATION: 'n/a',
cte.POST_OFFICE: 'MediumOffice',
cte.LIBRARY: 'MediumOffice',
cte.EDUCATION: 'SecondarySchool',
cte.PRIMARY_SCHOOL: 'PrimarySchool',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'PrimarySchool',
cte.SECONDARY_SCHOOL: 'SecondarySchool',
cte.UNIVERSITY: 'SecondarySchool',
cte.LABORATORY_AND_RESEARCH_CENTER: 'SecondarySchool',
cte.STAND_ALONE_RETAIL: 'RetailStandalone',
cte.HOSPITAL: 'Hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'Outpatient',
cte.HEALTH_CARE: 'Outpatient',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'SmallHotel',
cte.COMMERCIAL: 'RetailStripmall',
cte.STRIP_MALL: 'RetailStripmall',
cte.SUPERMARKET: 'RetailStripmall',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'RetailStandalone',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'RetailStandalone',
cte.RESTAURANT: 'FullServiceRestaurant',
cte.QUICK_SERVICE_RESTAURANT: 'QuickServiceRestaurant',
cte.FULL_SERVICE_RESTAURANT: 'FullServiceRestaurant',
cte.HOTEL: 'SmallHotel',
cte.HOTEL_MEDIUM_CLASS: 'SmallHotel',
cte.SMALL_HOTEL: 'SmallHotel',
cte.LARGE_HOTEL: 'LargeHotel',
cte.DORMITORY: 'SmallHotel',
cte.EVENT_LOCATION: 'n/a',
cte.CONVENTION_CENTER: 'n/a',
cte.HALL: 'n/a',
cte.GREEN_HOUSE: 'n/a',
cte.INDUSTRY: 'n/a',
cte.WORKSHOP: 'n/a',
cte.WAREHOUSE: 'Warehouse',
cte.WAREHOUSE_REFRIGERATED: 'Warehouse',
cte.SPORTS_LOCATION: 'n/a',
cte.SPORTS_ARENA: 'n/a',
cte.GYMNASIUM: 'n/a',
cte.MOTION_PICTURE_THEATRE: 'n/a',
cte.MUSEUM: 'n/a',
cte.PERFORMING_ARTS_THEATRE: 'n/a',
cte.TRANSPORTATION: 'n/a',
cte.AUTOMOTIVE_FACILITY: 'n/a',
cte.PARKING_GARAGE: 'n/a',
cte.RELIGIOUS: 'n/a',
cte.NON_HEATED: 'n/a'
}
@property
def dictionary(self) -> dict:

View File

@ -12,66 +12,66 @@ class HubFunctionToNrelConstructionFunction:
def __init__(self):
self._dictionary = {
cte.RESIDENTIAL: 'residential',
cte.SINGLE_FAMILY_HOUSE: 'residential',
cte.MULTI_FAMILY_HOUSE: 'midrise apartment',
cte.ROW_HOUSE: 'midrise apartment',
cte.MID_RISE_APARTMENT: 'midrise apartment',
cte.HIGH_RISE_APARTMENT: 'high-rise apartment',
cte.OFFICE_AND_ADMINISTRATION: 'medium office',
cte.SMALL_OFFICE: 'small office',
cte.MEDIUM_OFFICE: 'medium office',
cte.LARGE_OFFICE: 'large office',
cte.COURTHOUSE: 'medium office',
cte.FIRE_STATION: 'n/a',
cte.PENITENTIARY: 'large hotel',
cte.POLICE_STATION: 'n/a',
cte.POST_OFFICE: 'medium office',
cte.LIBRARY: 'medium office',
cte.EDUCATION: 'secondary school',
cte.PRIMARY_SCHOOL: 'primary school',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'primary school',
cte.SECONDARY_SCHOOL: 'secondary school',
cte.UNIVERSITY: 'secondary school',
cte.LABORATORY_AND_RESEARCH_CENTER: 'secondary school',
cte.STAND_ALONE_RETAIL: 'stand-alone retail',
cte.HOSPITAL: 'hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'outpatient healthcare',
cte.HEALTH_CARE: 'outpatient healthcare',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'small hotel',
cte.COMMERCIAL: 'strip mall',
cte.STRIP_MALL: 'strip mall',
cte.SUPERMARKET: 'supermarket',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'stand-alone retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'stand-alone retail',
cte.RESTAURANT: 'full service restaurant',
cte.QUICK_SERVICE_RESTAURANT: 'quick service restaurant',
cte.FULL_SERVICE_RESTAURANT: 'full service restaurant',
cte.HOTEL: 'small hotel',
cte.HOTEL_MEDIUM_CLASS: 'small hotel',
cte.SMALL_HOTEL: 'small hotel',
cte.LARGE_HOTEL: 'large hotel',
cte.DORMITORY: 'small hotel',
cte.EVENT_LOCATION: 'n/a',
cte.CONVENTION_CENTER: 'n/a',
cte.HALL: 'n/a',
cte.GREEN_HOUSE: 'n/a',
cte.INDUSTRY: 'n/a',
cte.WORKSHOP: 'n/a',
cte.WAREHOUSE: 'warehouse',
cte.WAREHOUSE_REFRIGERATED: 'warehouse',
cte.SPORTS_LOCATION: 'n/a',
cte.SPORTS_ARENA: 'n/a',
cte.GYMNASIUM: 'n/a',
cte.MOTION_PICTURE_THEATRE: 'n/a',
cte.MUSEUM: 'n/a',
cte.PERFORMING_ARTS_THEATRE: 'n/a',
cte.TRANSPORTATION: 'n/a',
cte.AUTOMOTIVE_FACILITY: 'n/aquebec_to_hub',
cte.PARKING_GARAGE: 'n/a',
cte.RELIGIOUS: 'n/a',
cte.NON_HEATED: 'n/a'
}
cte.RESIDENTIAL: 'residential',
cte.SINGLE_FAMILY_HOUSE: 'residential',
cte.MULTI_FAMILY_HOUSE: 'midrise apartment',
cte.ROW_HOUSE: 'midrise apartment',
cte.MID_RISE_APARTMENT: 'midrise apartment',
cte.HIGH_RISE_APARTMENT: 'high-rise apartment',
cte.OFFICE_AND_ADMINISTRATION: 'medium office',
cte.SMALL_OFFICE: 'small office',
cte.MEDIUM_OFFICE: 'medium office',
cte.LARGE_OFFICE: 'large office',
cte.COURTHOUSE: 'medium office',
cte.FIRE_STATION: 'n/a',
cte.PENITENTIARY: 'large hotel',
cte.POLICE_STATION: 'n/a',
cte.POST_OFFICE: 'medium office',
cte.LIBRARY: 'medium office',
cte.EDUCATION: 'secondary school',
cte.PRIMARY_SCHOOL: 'primary school',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'primary school',
cte.SECONDARY_SCHOOL: 'secondary school',
cte.UNIVERSITY: 'secondary school',
cte.LABORATORY_AND_RESEARCH_CENTER: 'secondary school',
cte.STAND_ALONE_RETAIL: 'stand-alone retail',
cte.HOSPITAL: 'hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'outpatient healthcare',
cte.HEALTH_CARE: 'outpatient healthcare',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'small hotel',
cte.COMMERCIAL: 'strip mall',
cte.STRIP_MALL: 'strip mall',
cte.SUPERMARKET: 'supermarket',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'stand-alone retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'stand-alone retail',
cte.RESTAURANT: 'full service restaurant',
cte.QUICK_SERVICE_RESTAURANT: 'quick service restaurant',
cte.FULL_SERVICE_RESTAURANT: 'full service restaurant',
cte.HOTEL: 'small hotel',
cte.HOTEL_MEDIUM_CLASS: 'small hotel',
cte.SMALL_HOTEL: 'small hotel',
cte.LARGE_HOTEL: 'large hotel',
cte.DORMITORY: 'small hotel',
cte.EVENT_LOCATION: 'n/a',
cte.CONVENTION_CENTER: 'n/a',
cte.HALL: 'n/a',
cte.GREEN_HOUSE: 'n/a',
cte.INDUSTRY: 'n/a',
cte.WORKSHOP: 'n/a',
cte.WAREHOUSE: 'warehouse',
cte.WAREHOUSE_REFRIGERATED: 'warehouse',
cte.SPORTS_LOCATION: 'n/a',
cte.SPORTS_ARENA: 'n/a',
cte.GYMNASIUM: 'n/a',
cte.MOTION_PICTURE_THEATRE: 'n/a',
cte.MUSEUM: 'n/a',
cte.PERFORMING_ARTS_THEATRE: 'n/a',
cte.TRANSPORTATION: 'n/a',
cte.AUTOMOTIVE_FACILITY: 'n/aquebec_to_hub',
cte.PARKING_GARAGE: 'n/a',
cte.RELIGIOUS: 'n/a',
cte.NON_HEATED: 'n/a'
}
@property
def dictionary(self) -> dict:

View File

@ -12,66 +12,66 @@ class HubUsageToComnetUsage:
def __init__(self):
self._dictionary = {
cte.RESIDENTIAL: 'BA Multifamily',
cte.SINGLE_FAMILY_HOUSE: 'BA Multifamily',
cte.MULTI_FAMILY_HOUSE: 'BA Multifamily',
cte.ROW_HOUSE: 'BA Multifamily',
cte.MID_RISE_APARTMENT: 'BA Multifamily',
cte.HIGH_RISE_APARTMENT: 'BA Multifamily',
cte.OFFICE_AND_ADMINISTRATION: 'BA Office',
cte.SMALL_OFFICE: 'BA Office',
cte.MEDIUM_OFFICE: 'BA Office',
cte.LARGE_OFFICE: 'BA Office',
cte.COURTHOUSE: 'BA Courthouse',
cte.FIRE_STATION: 'BA Fire Station',
cte.PENITENTIARY: 'BA Penitentiary',
cte.POLICE_STATION: 'BA Police Station',
cte.POST_OFFICE: 'BA Post Office',
cte.LIBRARY: 'BA Library',
cte.EDUCATION: 'BA School/University',
cte.PRIMARY_SCHOOL: 'BA School/University',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'BA School/University',
cte.SECONDARY_SCHOOL: 'BA School/University',
cte.UNIVERSITY: 'BA School/University',
cte.LABORATORY_AND_RESEARCH_CENTER: 'BA School/University',
cte.STAND_ALONE_RETAIL: 'BA Retail',
cte.HOSPITAL: 'BA Hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'BA Healthcare Clinic',
cte.HEALTH_CARE: 'BA Healthcare Clinic',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'BA Healthcare Clinic',
cte.COMMERCIAL: 'BA Retail',
cte.STRIP_MALL: 'BA Retail',
cte.SUPERMARKET: 'BA Retail',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'BA Retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'BA Retail',
cte.RESTAURANT: 'BA Dining: Bar Lounge/Leisure',
cte.QUICK_SERVICE_RESTAURANT: 'BA Dining: Cafeteria/Fast Food',
cte.FULL_SERVICE_RESTAURANT: 'BA Dining: Bar Lounge/Leisure',
cte.HOTEL: 'BA Hotel',
cte.HOTEL_MEDIUM_CLASS: 'BA Motel',
cte.SMALL_HOTEL: 'BA Motel',
cte.LARGE_HOTEL: 'BA Hotel',
cte.DORMITORY: 'BA Dormitory',
cte.EVENT_LOCATION: 'BA Convention Center',
cte.CONVENTION_CENTER: 'BA Convention Center',
cte.HALL: 'BA Town Hall',
cte.GREEN_HOUSE: 'n/a',
cte.INDUSTRY: 'BA Manufacturing Facility',
cte.WORKSHOP: 'BA Workshop',
cte.WAREHOUSE: 'BA Warehouse',
cte.WAREHOUSE_REFRIGERATED: 'BA Warehouse',
cte.SPORTS_LOCATION: 'BA Exercise Center',
cte.SPORTS_ARENA: 'BA Sports Arena',
cte.GYMNASIUM: 'BA Gymnasium',
cte.MOTION_PICTURE_THEATRE: 'BA Motion Picture Theater',
cte.MUSEUM: 'BA Museum',
cte.PERFORMING_ARTS_THEATRE: 'BA Performing Arts Theater',
cte.TRANSPORTATION: 'BA Transportation',
cte.AUTOMOTIVE_FACILITY: 'BA Automotive Facility',
cte.PARKING_GARAGE: 'BA Parking Garage',
cte.RELIGIOUS: 'BA Religious Building',
cte.NON_HEATED: 'n/a'
}
cte.RESIDENTIAL: 'BA Multifamily',
cte.SINGLE_FAMILY_HOUSE: 'BA Multifamily',
cte.MULTI_FAMILY_HOUSE: 'BA Multifamily',
cte.ROW_HOUSE: 'BA Multifamily',
cte.MID_RISE_APARTMENT: 'BA Multifamily',
cte.HIGH_RISE_APARTMENT: 'BA Multifamily',
cte.OFFICE_AND_ADMINISTRATION: 'BA Office',
cte.SMALL_OFFICE: 'BA Office',
cte.MEDIUM_OFFICE: 'BA Office',
cte.LARGE_OFFICE: 'BA Office',
cte.COURTHOUSE: 'BA Courthouse',
cte.FIRE_STATION: 'BA Fire Station',
cte.PENITENTIARY: 'BA Penitentiary',
cte.POLICE_STATION: 'BA Police Station',
cte.POST_OFFICE: 'BA Post Office',
cte.LIBRARY: 'BA Library',
cte.EDUCATION: 'BA School/University',
cte.PRIMARY_SCHOOL: 'BA School/University',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'BA School/University',
cte.SECONDARY_SCHOOL: 'BA School/University',
cte.UNIVERSITY: 'BA School/University',
cte.LABORATORY_AND_RESEARCH_CENTER: 'BA School/University',
cte.STAND_ALONE_RETAIL: 'BA Retail',
cte.HOSPITAL: 'BA Hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'BA Healthcare Clinic',
cte.HEALTH_CARE: 'BA Healthcare Clinic',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'BA Healthcare Clinic',
cte.COMMERCIAL: 'BA Retail',
cte.STRIP_MALL: 'BA Retail',
cte.SUPERMARKET: 'BA Retail',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'BA Retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'BA Retail',
cte.RESTAURANT: 'BA Dining: Bar Lounge/Leisure',
cte.QUICK_SERVICE_RESTAURANT: 'BA Dining: Cafeteria/Fast Food',
cte.FULL_SERVICE_RESTAURANT: 'BA Dining: Bar Lounge/Leisure',
cte.HOTEL: 'BA Hotel',
cte.HOTEL_MEDIUM_CLASS: 'BA Motel',
cte.SMALL_HOTEL: 'BA Motel',
cte.LARGE_HOTEL: 'BA Hotel',
cte.DORMITORY: 'BA Dormitory',
cte.EVENT_LOCATION: 'BA Convention Center',
cte.CONVENTION_CENTER: 'BA Convention Center',
cte.HALL: 'BA Town Hall',
cte.GREEN_HOUSE: 'n/a',
cte.INDUSTRY: 'BA Manufacturing Facility',
cte.WORKSHOP: 'BA Workshop',
cte.WAREHOUSE: 'BA Warehouse',
cte.WAREHOUSE_REFRIGERATED: 'BA Warehouse',
cte.SPORTS_LOCATION: 'BA Exercise Center',
cte.SPORTS_ARENA: 'BA Sports Arena',
cte.GYMNASIUM: 'BA Gymnasium',
cte.MOTION_PICTURE_THEATRE: 'BA Motion Picture Theater',
cte.MUSEUM: 'BA Museum',
cte.PERFORMING_ARTS_THEATRE: 'BA Performing Arts Theater',
cte.TRANSPORTATION: 'BA Transportation',
cte.AUTOMOTIVE_FACILITY: 'BA Automotive Facility',
cte.PARKING_GARAGE: 'BA Parking Garage',
cte.RELIGIOUS: 'BA Religious Building',
cte.NON_HEATED: 'n/a'
}
@property
def dictionary(self) -> dict:

View File

@ -12,66 +12,66 @@ class HubUsageToHftUsage:
def __init__(self):
self._dictionary = {
cte.RESIDENTIAL: 'residential',
cte.SINGLE_FAMILY_HOUSE: 'single family house',
cte.MULTI_FAMILY_HOUSE: 'multifamily house',
cte.ROW_HOUSE: 'single family house',
cte.MID_RISE_APARTMENT: 'multifamily house',
cte.HIGH_RISE_APARTMENT: 'multifamily house',
cte.OFFICE_AND_ADMINISTRATION: 'office and administration',
cte.SMALL_OFFICE: 'office and administration',
cte.MEDIUM_OFFICE: 'office and administration',
cte.LARGE_OFFICE: 'office and administration',
cte.COURTHOUSE: 'office and administration',
cte.FIRE_STATION: 'office and administration',
cte.PENITENTIARY: 'school with shower',
cte.POLICE_STATION: 'office and administration',
cte.POST_OFFICE: 'office and administration',
cte.LIBRARY: 'office and administration',
cte.EDUCATION: 'education',
cte.PRIMARY_SCHOOL: 'school without shower',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'school with shower',
cte.SECONDARY_SCHOOL: 'education',
cte.UNIVERSITY: 'education',
cte.LABORATORY_AND_RESEARCH_CENTER: 'laboratory and research centers',
cte.STAND_ALONE_RETAIL: 'retail',
cte.HOSPITAL: 'health care',
cte.OUT_PATIENT_HEALTH_CARE: 'health care',
cte.HEALTH_CARE: 'health care',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Home for the aged or orphanage',
cte.COMMERCIAL: 'retail',
cte.STRIP_MALL: 'retail',
cte.SUPERMARKET: 'retail shop / refrigerated food',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'retail shop / refrigerated food',
cte.RESTAURANT: 'restaurant',
cte.QUICK_SERVICE_RESTAURANT: 'restaurant',
cte.FULL_SERVICE_RESTAURANT: 'restaurant',
cte.HOTEL: 'hotel',
cte.HOTEL_MEDIUM_CLASS: 'hotel (Medium-class)',
cte.SMALL_HOTEL: 'hotel',
cte.LARGE_HOTEL: 'hotel',
cte.DORMITORY: 'dormitory',
cte.EVENT_LOCATION: 'event location',
cte.CONVENTION_CENTER: 'event location',
cte.HALL: 'hall',
cte.GREEN_HOUSE: 'green house',
cte.INDUSTRY: 'industry',
cte.WORKSHOP: 'industry',
cte.WAREHOUSE: 'industry',
cte.WAREHOUSE_REFRIGERATED: 'industry',
cte.SPORTS_LOCATION: 'sport location',
cte.SPORTS_ARENA: 'sport location',
cte.GYMNASIUM: 'sport location',
cte.MOTION_PICTURE_THEATRE: 'event location',
cte.MUSEUM: 'event location',
cte.PERFORMING_ARTS_THEATRE: 'event location',
cte.TRANSPORTATION: 'n/a',
cte.AUTOMOTIVE_FACILITY: 'n/a',
cte.PARKING_GARAGE: 'n/a',
cte.RELIGIOUS: 'event location',
cte.NON_HEATED: 'non-heated'
}
cte.RESIDENTIAL: 'residential',
cte.SINGLE_FAMILY_HOUSE: 'single family house',
cte.MULTI_FAMILY_HOUSE: 'multifamily house',
cte.ROW_HOUSE: 'single family house',
cte.MID_RISE_APARTMENT: 'multifamily house',
cte.HIGH_RISE_APARTMENT: 'multifamily house',
cte.OFFICE_AND_ADMINISTRATION: 'office and administration',
cte.SMALL_OFFICE: 'office and administration',
cte.MEDIUM_OFFICE: 'office and administration',
cte.LARGE_OFFICE: 'office and administration',
cte.COURTHOUSE: 'office and administration',
cte.FIRE_STATION: 'office and administration',
cte.PENITENTIARY: 'school with shower',
cte.POLICE_STATION: 'office and administration',
cte.POST_OFFICE: 'office and administration',
cte.LIBRARY: 'office and administration',
cte.EDUCATION: 'education',
cte.PRIMARY_SCHOOL: 'school without shower',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'school with shower',
cte.SECONDARY_SCHOOL: 'education',
cte.UNIVERSITY: 'education',
cte.LABORATORY_AND_RESEARCH_CENTER: 'laboratory and research centers',
cte.STAND_ALONE_RETAIL: 'retail',
cte.HOSPITAL: 'health care',
cte.OUT_PATIENT_HEALTH_CARE: 'health care',
cte.HEALTH_CARE: 'health care',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Home for the aged or orphanage',
cte.COMMERCIAL: 'retail',
cte.STRIP_MALL: 'retail',
cte.SUPERMARKET: 'retail shop / refrigerated food',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'retail shop / refrigerated food',
cte.RESTAURANT: 'restaurant',
cte.QUICK_SERVICE_RESTAURANT: 'restaurant',
cte.FULL_SERVICE_RESTAURANT: 'restaurant',
cte.HOTEL: 'hotel',
cte.HOTEL_MEDIUM_CLASS: 'hotel (Medium-class)',
cte.SMALL_HOTEL: 'hotel',
cte.LARGE_HOTEL: 'hotel',
cte.DORMITORY: 'dormitory',
cte.EVENT_LOCATION: 'event location',
cte.CONVENTION_CENTER: 'event location',
cte.HALL: 'hall',
cte.GREEN_HOUSE: 'green house',
cte.INDUSTRY: 'industry',
cte.WORKSHOP: 'industry',
cte.WAREHOUSE: 'industry',
cte.WAREHOUSE_REFRIGERATED: 'industry',
cte.SPORTS_LOCATION: 'sport location',
cte.SPORTS_ARENA: 'sport location',
cte.GYMNASIUM: 'sport location',
cte.MOTION_PICTURE_THEATRE: 'event location',
cte.MUSEUM: 'event location',
cte.PERFORMING_ARTS_THEATRE: 'event location',
cte.TRANSPORTATION: 'n/a',
cte.AUTOMOTIVE_FACILITY: 'n/a',
cte.PARKING_GARAGE: 'n/a',
cte.RELIGIOUS: 'event location',
cte.NON_HEATED: 'non-heated'
}
@property
def dictionary(self) -> dict:

View File

@ -12,66 +12,66 @@ class HubUsageToNrcanUsage:
def __init__(self):
self._dictionary = {
cte.RESIDENTIAL: 'Multi-unit residential building',
cte.SINGLE_FAMILY_HOUSE: 'Multi-unit residential building',
cte.MULTI_FAMILY_HOUSE: 'Multi-unit residential building',
cte.ROW_HOUSE: 'Multi-unit residential building',
cte.MID_RISE_APARTMENT: 'Multi-unit residential building',
cte.HIGH_RISE_APARTMENT: 'Multi-unit residential building',
cte.OFFICE_AND_ADMINISTRATION: 'Office',
cte.SMALL_OFFICE: 'Office',
cte.MEDIUM_OFFICE: 'Office',
cte.LARGE_OFFICE: 'Office',
cte.COURTHOUSE: 'Courthouse',
cte.FIRE_STATION: 'Fire station',
cte.PENITENTIARY: 'Penitentiary',
cte.POLICE_STATION: 'Police station',
cte.POST_OFFICE: 'Post office',
cte.LIBRARY: 'Library',
cte.EDUCATION: 'School/university',
cte.PRIMARY_SCHOOL: 'School/university',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'School/university',
cte.SECONDARY_SCHOOL: 'School/university',
cte.UNIVERSITY: 'School/university',
cte.LABORATORY_AND_RESEARCH_CENTER: 'School/university',
cte.STAND_ALONE_RETAIL: 'Retail',
cte.HOSPITAL: 'Hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'Health-care clinic',
cte.HEALTH_CARE: 'Health-care clinic',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Health-care clinic',
cte.COMMERCIAL: 'Retail',
cte.STRIP_MALL: 'Retail',
cte.SUPERMARKET: 'Retail',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'Retail',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'Retail',
cte.RESTAURANT: 'Dining - bar/lounge',
cte.QUICK_SERVICE_RESTAURANT: 'Dining - cafeteria',
cte.FULL_SERVICE_RESTAURANT: 'Dining - bar/lounge',
cte.HOTEL: 'Hotel',
cte.HOTEL_MEDIUM_CLASS: 'Motel',
cte.SMALL_HOTEL: 'Motel',
cte.LARGE_HOTEL: 'Hotel',
cte.DORMITORY: 'Dormitory',
cte.EVENT_LOCATION: 'Convention centre',
cte.CONVENTION_CENTER: 'Convention centre',
cte.HALL: 'Town hall',
cte.GREEN_HOUSE: 'n/a',
cte.INDUSTRY: 'Manufacturing facility',
cte.WORKSHOP: 'Workshop',
cte.WAREHOUSE: 'Warehouse',
cte.WAREHOUSE_REFRIGERATED: 'Warehouse - refrigerated',
cte.SPORTS_LOCATION: 'Exercise centre',
cte.SPORTS_ARENA: 'Sports arena',
cte.GYMNASIUM: 'Gymnasium',
cte.MOTION_PICTURE_THEATRE: 'Motion picture theatre',
cte.MUSEUM: 'Museum',
cte.PERFORMING_ARTS_THEATRE: 'Performing arts theatre',
cte.TRANSPORTATION: 'Transportation',
cte.AUTOMOTIVE_FACILITY: 'Automotive facility',
cte.PARKING_GARAGE: 'Parking garage',
cte.RELIGIOUS: 'Religious',
cte.NON_HEATED: 'n/a'
}
cte.RESIDENTIAL: 'Multi-unit residential building',
cte.SINGLE_FAMILY_HOUSE: 'Multi-unit residential building',
cte.MULTI_FAMILY_HOUSE: 'Multi-unit residential building',
cte.ROW_HOUSE: 'Multi-unit residential building',
cte.MID_RISE_APARTMENT: 'Multi-unit residential building',
cte.HIGH_RISE_APARTMENT: 'Multi-unit residential building',
cte.OFFICE_AND_ADMINISTRATION: 'Office',
cte.SMALL_OFFICE: 'Office',
cte.MEDIUM_OFFICE: 'Office',
cte.LARGE_OFFICE: 'Office',
cte.COURTHOUSE: 'Courthouse',
cte.FIRE_STATION: 'Fire station',
cte.PENITENTIARY: 'Penitentiary',
cte.POLICE_STATION: 'Police station',
cte.POST_OFFICE: 'Post office',
cte.LIBRARY: 'Library',
cte.EDUCATION: 'School/university',
cte.PRIMARY_SCHOOL: 'School/university',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'School/university',
cte.SECONDARY_SCHOOL: 'School/university',
cte.UNIVERSITY: 'School/university',
cte.LABORATORY_AND_RESEARCH_CENTER: 'School/university',
cte.STAND_ALONE_RETAIL: 'Retail area',
cte.HOSPITAL: 'Hospital',
cte.OUT_PATIENT_HEALTH_CARE: 'Health-care clinic',
cte.HEALTH_CARE: 'Health-care clinic',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'Health-care clinic',
cte.COMMERCIAL: 'Retail area',
cte.STRIP_MALL: 'Retail area',
cte.SUPERMARKET: 'Retail area',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'Retail area',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'Retail area',
cte.RESTAURANT: 'Dining - bar/lounge',
cte.QUICK_SERVICE_RESTAURANT: 'Dining - cafeteria',
cte.FULL_SERVICE_RESTAURANT: 'Dining - bar/lounge',
cte.HOTEL: 'Hotel',
cte.HOTEL_MEDIUM_CLASS: 'Motel',
cte.SMALL_HOTEL: 'Motel',
cte.LARGE_HOTEL: 'Hotel',
cte.DORMITORY: 'Dormitory',
cte.EVENT_LOCATION: 'Convention centre',
cte.CONVENTION_CENTER: 'Convention centre',
cte.HALL: 'Town hall',
cte.GREEN_HOUSE: 'n/a',
cte.INDUSTRY: 'Manufacturing facility',
cte.WORKSHOP: 'Workshop',
cte.WAREHOUSE: 'Warehouse',
cte.WAREHOUSE_REFRIGERATED: 'Warehouse - refrigerated',
cte.SPORTS_LOCATION: 'Exercise centre',
cte.SPORTS_ARENA: 'Sports arena',
cte.GYMNASIUM: 'Gymnasium',
cte.MOTION_PICTURE_THEATRE: 'Motion picture theatre',
cte.MUSEUM: 'Museum',
cte.PERFORMING_ARTS_THEATRE: 'Performing arts theatre',
cte.TRANSPORTATION: 'Transportation',
cte.AUTOMOTIVE_FACILITY: 'Automotive facility',
cte.PARKING_GARAGE: 'Parking garage',
cte.RELIGIOUS: 'Religious',
cte.NON_HEATED: 'n/a'
}
@property
def dictionary(self) -> dict:

View File

@ -12,205 +12,205 @@ class PlutoFunctionToHubFunction:
def __init__(self):
self._dictionary = {
'A0': cte.SINGLE_FAMILY_HOUSE,
'A1': cte.SINGLE_FAMILY_HOUSE,
'A2': cte.SINGLE_FAMILY_HOUSE,
'A3': cte.SINGLE_FAMILY_HOUSE,
'A4': cte.SINGLE_FAMILY_HOUSE,
'A5': cte.SINGLE_FAMILY_HOUSE,
'A6': cte.SINGLE_FAMILY_HOUSE,
'A7': cte.SINGLE_FAMILY_HOUSE,
'A8': cte.SINGLE_FAMILY_HOUSE,
'A9': cte.SINGLE_FAMILY_HOUSE,
'B1': cte.MULTI_FAMILY_HOUSE,
'B2': cte.MULTI_FAMILY_HOUSE,
'B3': cte.MULTI_FAMILY_HOUSE,
'B9': cte.MULTI_FAMILY_HOUSE,
'C0': cte.RESIDENTIAL,
'C1': cte.RESIDENTIAL,
'C2': cte.RESIDENTIAL,
'C3': cte.RESIDENTIAL,
'C4': cte.RESIDENTIAL,
'C5': cte.RESIDENTIAL,
'C6': cte.RESIDENTIAL,
'C7': cte.RESIDENTIAL,
'C8': cte.RESIDENTIAL,
'C9': cte.RESIDENTIAL,
'D0': cte.RESIDENTIAL,
'D1': cte.RESIDENTIAL,
'D2': cte.RESIDENTIAL,
'D3': cte.RESIDENTIAL,
'D4': cte.RESIDENTIAL,
'D5': cte.RESIDENTIAL,
'D6': cte.RESIDENTIAL,
'D7': cte.RESIDENTIAL,
'D8': cte.RESIDENTIAL,
'D9': cte.RESIDENTIAL,
'E1': cte.WAREHOUSE,
'E3': cte.WAREHOUSE,
'E4': cte.WAREHOUSE,
'E5': cte.WAREHOUSE,
'E7': cte.WAREHOUSE,
'E9': cte.WAREHOUSE,
'F1': cte.WAREHOUSE,
'F2': cte.WAREHOUSE,
'F4': cte.WAREHOUSE,
'F5': cte.WAREHOUSE,
'F8': cte.WAREHOUSE,
'F9': cte.WAREHOUSE,
'G0': cte.SMALL_OFFICE,
'G1': cte.SMALL_OFFICE,
'G2': cte.SMALL_OFFICE,
'G3': cte.SMALL_OFFICE,
'G4': cte.SMALL_OFFICE,
'G5': cte.SMALL_OFFICE,
'G6': cte.SMALL_OFFICE,
'G7': cte.SMALL_OFFICE,
'G8': cte.SMALL_OFFICE,
'G9': cte.SMALL_OFFICE,
'H1': cte.HOTEL,
'H2': cte.HOTEL,
'H3': cte.HOTEL,
'H4': cte.HOTEL,
'H5': cte.HOTEL,
'H6': cte.HOTEL,
'H7': cte.HOTEL,
'H8': cte.HOTEL,
'H9': cte.HOTEL,
'HB': cte.HOTEL,
'HH': cte.HOTEL,
'HR': cte.HOTEL,
'HS': cte.HOTEL,
'I1': cte.HOSPITAL,
'I2': cte.OUT_PATIENT_HEALTH_CARE,
'I3': cte.OUT_PATIENT_HEALTH_CARE,
'I4': cte.RESIDENTIAL,
'I5': cte.OUT_PATIENT_HEALTH_CARE,
'I6': cte.OUT_PATIENT_HEALTH_CARE,
'I7': cte.OUT_PATIENT_HEALTH_CARE,
'I9': cte.OUT_PATIENT_HEALTH_CARE,
'J1': cte.LARGE_OFFICE,
'J2': cte.LARGE_OFFICE,
'J3': cte.LARGE_OFFICE,
'J4': cte.LARGE_OFFICE,
'J5': cte.LARGE_OFFICE,
'J6': cte.LARGE_OFFICE,
'J7': cte.LARGE_OFFICE,
'J8': cte.LARGE_OFFICE,
'J9': cte.LARGE_OFFICE,
'K1': cte.STRIP_MALL,
'K2': cte.STRIP_MALL,
'K3': cte.STRIP_MALL,
'K4': cte.RESIDENTIAL,
'K5': cte.RESTAURANT,
'K6': cte.SUPERMARKET,
'K7': cte.SUPERMARKET,
'K8': cte.SUPERMARKET,
'K9': cte.SUPERMARKET,
'L1': cte.RESIDENTIAL,
'L2': cte.RESIDENTIAL,
'L3': cte.RESIDENTIAL,
'L8': cte.RESIDENTIAL,
'L9': cte.RESIDENTIAL,
'M1': cte.LARGE_OFFICE,
'M2': cte.LARGE_OFFICE,
'M3': cte.LARGE_OFFICE,
'M4': cte.LARGE_OFFICE,
'M9': cte.LARGE_OFFICE,
'N1': cte.RESIDENTIAL,
'N2': cte.RESIDENTIAL,
'N3': cte.RESIDENTIAL,
'N4': cte.RESIDENTIAL,
'N9': cte.RESIDENTIAL,
'O1': cte.SMALL_OFFICE,
'O2': cte.SMALL_OFFICE,
'O3': cte.SMALL_OFFICE,
'O4': cte.SMALL_OFFICE,
'O5': cte.SMALL_OFFICE,
'O6': cte.SMALL_OFFICE,
'O7': cte.SMALL_OFFICE,
'O8': cte.SMALL_OFFICE,
'O9': cte.SMALL_OFFICE,
'P1': cte.LARGE_OFFICE,
'P2': cte.HOTEL,
'P3': cte.SMALL_OFFICE,
'P4': cte.SMALL_OFFICE,
'P5': cte.SMALL_OFFICE,
'P6': cte.SMALL_OFFICE,
'P7': cte.LARGE_OFFICE,
'P8': cte.LARGE_OFFICE,
'P9': cte.SMALL_OFFICE,
'Q0': cte.SMALL_OFFICE,
'Q1': cte.SMALL_OFFICE,
'Q2': cte.SMALL_OFFICE,
'Q3': cte.SMALL_OFFICE,
'Q4': cte.SMALL_OFFICE,
'Q5': cte.SMALL_OFFICE,
'Q6': cte.SMALL_OFFICE,
'Q7': cte.SMALL_OFFICE,
'Q8': cte.SMALL_OFFICE,
'Q9': cte.SMALL_OFFICE,
'R0': cte.RESIDENTIAL,
'R1': cte.RESIDENTIAL,
'R2': cte.RESIDENTIAL,
'R3': cte.RESIDENTIAL,
'R4': cte.RESIDENTIAL,
'R5': cte.RESIDENTIAL,
'R6': cte.RESIDENTIAL,
'R7': cte.RESIDENTIAL,
'R8': cte.RESIDENTIAL,
'R9': cte.RESIDENTIAL,
'RA': cte.RESIDENTIAL,
'RB': cte.RESIDENTIAL,
'RC': cte.RESIDENTIAL,
'RD': cte.RESIDENTIAL,
'RG': cte.RESIDENTIAL,
'RH': cte.RESIDENTIAL,
'RI': cte.RESIDENTIAL,
'RK': cte.RESIDENTIAL,
'RM': cte.RESIDENTIAL,
'RR': cte.RESIDENTIAL,
'RS': cte.RESIDENTIAL,
'RW': cte.RESIDENTIAL,
'RX': cte.RESIDENTIAL,
'RZ': cte.RESIDENTIAL,
'S0': cte.RESIDENTIAL,
'S1': cte.RESIDENTIAL,
'S2': cte.RESIDENTIAL,
'S3': cte.RESIDENTIAL,
'S4': cte.RESIDENTIAL,
'S5': cte.RESIDENTIAL,
'S9': cte.RESIDENTIAL,
'U0': cte.WAREHOUSE,
'U1': cte.WAREHOUSE,
'U2': cte.WAREHOUSE,
'U3': cte.WAREHOUSE,
'U4': cte.WAREHOUSE,
'U5': cte.WAREHOUSE,
'U6': cte.WAREHOUSE,
'U7': cte.WAREHOUSE,
'U8': cte.WAREHOUSE,
'U9': cte.WAREHOUSE,
'W1': cte.PRIMARY_SCHOOL,
'W2': cte.PRIMARY_SCHOOL,
'W3': cte.SECONDARY_SCHOOL,
'W4': cte.EDUCATION,
'W5': cte.SECONDARY_SCHOOL,
'W6': cte.SECONDARY_SCHOOL,
'W7': cte.SECONDARY_SCHOOL,
'W8': cte.PRIMARY_SCHOOL,
'W9': cte.SECONDARY_SCHOOL,
'Y1': cte.LARGE_OFFICE,
'Y2': cte.LARGE_OFFICE,
'Y3': cte.LARGE_OFFICE,
'Y4': cte.LARGE_OFFICE,
'Y5': cte.LARGE_OFFICE,
'Y6': cte.LARGE_OFFICE,
'Y7': cte.LARGE_OFFICE,
'Y8': cte.LARGE_OFFICE,
'Y9': cte.LARGE_OFFICE,
'Z1': cte.LARGE_OFFICE
}
'A0': cte.SINGLE_FAMILY_HOUSE,
'A1': cte.SINGLE_FAMILY_HOUSE,
'A2': cte.SINGLE_FAMILY_HOUSE,
'A3': cte.SINGLE_FAMILY_HOUSE,
'A4': cte.SINGLE_FAMILY_HOUSE,
'A5': cte.SINGLE_FAMILY_HOUSE,
'A6': cte.SINGLE_FAMILY_HOUSE,
'A7': cte.SINGLE_FAMILY_HOUSE,
'A8': cte.SINGLE_FAMILY_HOUSE,
'A9': cte.SINGLE_FAMILY_HOUSE,
'B1': cte.MULTI_FAMILY_HOUSE,
'B2': cte.MULTI_FAMILY_HOUSE,
'B3': cte.MULTI_FAMILY_HOUSE,
'B9': cte.MULTI_FAMILY_HOUSE,
'C0': cte.RESIDENTIAL,
'C1': cte.RESIDENTIAL,
'C2': cte.RESIDENTIAL,
'C3': cte.RESIDENTIAL,
'C4': cte.RESIDENTIAL,
'C5': cte.RESIDENTIAL,
'C6': cte.RESIDENTIAL,
'C7': cte.RESIDENTIAL,
'C8': cte.RESIDENTIAL,
'C9': cte.RESIDENTIAL,
'D0': cte.RESIDENTIAL,
'D1': cte.RESIDENTIAL,
'D2': cte.RESIDENTIAL,
'D3': cte.RESIDENTIAL,
'D4': cte.RESIDENTIAL,
'D5': cte.RESIDENTIAL,
'D6': cte.RESIDENTIAL,
'D7': cte.RESIDENTIAL,
'D8': cte.RESIDENTIAL,
'D9': cte.RESIDENTIAL,
'E1': cte.WAREHOUSE,
'E3': cte.WAREHOUSE,
'E4': cte.WAREHOUSE,
'E5': cte.WAREHOUSE,
'E7': cte.WAREHOUSE,
'E9': cte.WAREHOUSE,
'F1': cte.WAREHOUSE,
'F2': cte.WAREHOUSE,
'F4': cte.WAREHOUSE,
'F5': cte.WAREHOUSE,
'F8': cte.WAREHOUSE,
'F9': cte.WAREHOUSE,
'G0': cte.SMALL_OFFICE,
'G1': cte.SMALL_OFFICE,
'G2': cte.SMALL_OFFICE,
'G3': cte.SMALL_OFFICE,
'G4': cte.SMALL_OFFICE,
'G5': cte.SMALL_OFFICE,
'G6': cte.SMALL_OFFICE,
'G7': cte.SMALL_OFFICE,
'G8': cte.SMALL_OFFICE,
'G9': cte.SMALL_OFFICE,
'H1': cte.HOTEL,
'H2': cte.HOTEL,
'H3': cte.HOTEL,
'H4': cte.HOTEL,
'H5': cte.HOTEL,
'H6': cte.HOTEL,
'H7': cte.HOTEL,
'H8': cte.HOTEL,
'H9': cte.HOTEL,
'HB': cte.HOTEL,
'HH': cte.HOTEL,
'HR': cte.HOTEL,
'HS': cte.HOTEL,
'I1': cte.HOSPITAL,
'I2': cte.OUT_PATIENT_HEALTH_CARE,
'I3': cte.OUT_PATIENT_HEALTH_CARE,
'I4': cte.RESIDENTIAL,
'I5': cte.OUT_PATIENT_HEALTH_CARE,
'I6': cte.OUT_PATIENT_HEALTH_CARE,
'I7': cte.OUT_PATIENT_HEALTH_CARE,
'I9': cte.OUT_PATIENT_HEALTH_CARE,
'J1': cte.LARGE_OFFICE,
'J2': cte.LARGE_OFFICE,
'J3': cte.LARGE_OFFICE,
'J4': cte.LARGE_OFFICE,
'J5': cte.LARGE_OFFICE,
'J6': cte.LARGE_OFFICE,
'J7': cte.LARGE_OFFICE,
'J8': cte.LARGE_OFFICE,
'J9': cte.LARGE_OFFICE,
'K1': cte.STRIP_MALL,
'K2': cte.STRIP_MALL,
'K3': cte.STRIP_MALL,
'K4': cte.RESIDENTIAL,
'K5': cte.RESTAURANT,
'K6': cte.SUPERMARKET,
'K7': cte.SUPERMARKET,
'K8': cte.SUPERMARKET,
'K9': cte.SUPERMARKET,
'L1': cte.RESIDENTIAL,
'L2': cte.RESIDENTIAL,
'L3': cte.RESIDENTIAL,
'L8': cte.RESIDENTIAL,
'L9': cte.RESIDENTIAL,
'M1': cte.LARGE_OFFICE,
'M2': cte.LARGE_OFFICE,
'M3': cte.LARGE_OFFICE,
'M4': cte.LARGE_OFFICE,
'M9': cte.LARGE_OFFICE,
'N1': cte.RESIDENTIAL,
'N2': cte.RESIDENTIAL,
'N3': cte.RESIDENTIAL,
'N4': cte.RESIDENTIAL,
'N9': cte.RESIDENTIAL,
'O1': cte.SMALL_OFFICE,
'O2': cte.SMALL_OFFICE,
'O3': cte.SMALL_OFFICE,
'O4': cte.SMALL_OFFICE,
'O5': cte.SMALL_OFFICE,
'O6': cte.SMALL_OFFICE,
'O7': cte.SMALL_OFFICE,
'O8': cte.SMALL_OFFICE,
'O9': cte.SMALL_OFFICE,
'P1': cte.LARGE_OFFICE,
'P2': cte.HOTEL,
'P3': cte.SMALL_OFFICE,
'P4': cte.SMALL_OFFICE,
'P5': cte.SMALL_OFFICE,
'P6': cte.SMALL_OFFICE,
'P7': cte.LARGE_OFFICE,
'P8': cte.LARGE_OFFICE,
'P9': cte.SMALL_OFFICE,
'Q0': cte.SMALL_OFFICE,
'Q1': cte.SMALL_OFFICE,
'Q2': cte.SMALL_OFFICE,
'Q3': cte.SMALL_OFFICE,
'Q4': cte.SMALL_OFFICE,
'Q5': cte.SMALL_OFFICE,
'Q6': cte.SMALL_OFFICE,
'Q7': cte.SMALL_OFFICE,
'Q8': cte.SMALL_OFFICE,
'Q9': cte.SMALL_OFFICE,
'R0': cte.RESIDENTIAL,
'R1': cte.RESIDENTIAL,
'R2': cte.RESIDENTIAL,
'R3': cte.RESIDENTIAL,
'R4': cte.RESIDENTIAL,
'R5': cte.RESIDENTIAL,
'R6': cte.RESIDENTIAL,
'R7': cte.RESIDENTIAL,
'R8': cte.RESIDENTIAL,
'R9': cte.RESIDENTIAL,
'RA': cte.RESIDENTIAL,
'RB': cte.RESIDENTIAL,
'RC': cte.RESIDENTIAL,
'RD': cte.RESIDENTIAL,
'RG': cte.RESIDENTIAL,
'RH': cte.RESIDENTIAL,
'RI': cte.RESIDENTIAL,
'RK': cte.RESIDENTIAL,
'RM': cte.RESIDENTIAL,
'RR': cte.RESIDENTIAL,
'RS': cte.RESIDENTIAL,
'RW': cte.RESIDENTIAL,
'RX': cte.RESIDENTIAL,
'RZ': cte.RESIDENTIAL,
'S0': cte.RESIDENTIAL,
'S1': cte.RESIDENTIAL,
'S2': cte.RESIDENTIAL,
'S3': cte.RESIDENTIAL,
'S4': cte.RESIDENTIAL,
'S5': cte.RESIDENTIAL,
'S9': cte.RESIDENTIAL,
'U0': cte.WAREHOUSE,
'U1': cte.WAREHOUSE,
'U2': cte.WAREHOUSE,
'U3': cte.WAREHOUSE,
'U4': cte.WAREHOUSE,
'U5': cte.WAREHOUSE,
'U6': cte.WAREHOUSE,
'U7': cte.WAREHOUSE,
'U8': cte.WAREHOUSE,
'U9': cte.WAREHOUSE,
'W1': cte.PRIMARY_SCHOOL,
'W2': cte.PRIMARY_SCHOOL,
'W3': cte.SECONDARY_SCHOOL,
'W4': cte.EDUCATION,
'W5': cte.SECONDARY_SCHOOL,
'W6': cte.SECONDARY_SCHOOL,
'W7': cte.SECONDARY_SCHOOL,
'W8': cte.PRIMARY_SCHOOL,
'W9': cte.SECONDARY_SCHOOL,
'Y1': cte.LARGE_OFFICE,
'Y2': cte.LARGE_OFFICE,
'Y3': cte.LARGE_OFFICE,
'Y4': cte.LARGE_OFFICE,
'Y5': cte.LARGE_OFFICE,
'Y6': cte.LARGE_OFFICE,
'Y7': cte.LARGE_OFFICE,
'Y8': cte.LARGE_OFFICE,
'Y9': cte.LARGE_OFFICE,
'Z1': cte.LARGE_OFFICE
}
@property
def dictionary(self) -> dict:

View File

@ -15,6 +15,7 @@ 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
class Dictionaries:
"""
Dictionaries class

View File

@ -16,6 +16,8 @@ from hub.city_model_structure.attributes.polygon import Polygon
from hub.city_model_structure.attributes.polyhedron import Polyhedron
from hub.helpers.location import Location
from PIL import Image
class MapPoint:
def __init__(self, x, y):
@ -63,7 +65,7 @@ class GeometryHelper:
return MapPoint(((city.upper_corner[0] - coordinate[0]) * 0.5), ((city.upper_corner[1] - coordinate[1]) * 0.5))
@staticmethod
def city_mapping(city, building_names=None):
def city_mapping(city, building_names=None, plot=False):
"""
Returns a shared_information dictionary like
@ -78,6 +80,8 @@ class GeometryHelper:
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)]
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
city_image = img.load() # create the pixel map
for building_name in building_names:
building = city.city_object(building_name)
line = 0
@ -103,13 +107,14 @@ class GeometryHelper:
'line_start': (coordinate[0], coordinate[1]),
'line_end': (next_coordinate[0], next_coordinate[1]),
}
city_image[x, y] = (100, 0, 0)
elif city_map[x][y] != building.name:
neighbour = city.city_object(city_map[x][y])
neighbour_info = map_info[x][y]
# prepare the keys
neighbour_start_coordinate = f'{neighbour_info["line_start"][0]}_{neighbour_info["line_start"][1]}'
building_start_coordinate = f'{coordinate[0]}_{coordinate[1]}'
neighbour_start_coordinate = f'{GeometryHelper.coordinate_to_map_point(neighbour_info["line_start"], city)}'
building_start_coordinate = f'{GeometryHelper.coordinate_to_map_point(coordinate, city)}'
neighbour_key = f'{neighbour.name}_{neighbour_start_coordinate}_{building_start_coordinate}'
building_key = f'{building.name}_{building_start_coordinate}_{neighbour_start_coordinate}'
@ -126,6 +131,10 @@ class GeometryHelper:
'line_end': (next_coordinate[0], next_coordinate[1]),
'neighbour_line_start': neighbour_info['line_start'],
'neighbour_line_end': neighbour_info['line_end'],
'coordinate_start': f"{GeometryHelper.coordinate_to_map_point(coordinate, city)}",
'coordinate_end': f"{GeometryHelper.coordinate_to_map_point(next_coordinate, city)}",
'neighbour_start': f"{GeometryHelper.coordinate_to_map_point(neighbour_info['line_start'], city)}",
'neighbour_end': f"{GeometryHelper.coordinate_to_map_point(neighbour_info['line_end'], city)}",
'shared_points': 1
}
@ -142,6 +151,10 @@ class GeometryHelper:
'line_end': neighbour_info['line_end'],
'neighbour_line_start': (coordinate[0], coordinate[1]),
'neighbour_line_end': (next_coordinate[0], next_coordinate[1]),
'neighbour_start': f"{GeometryHelper.coordinate_to_map_point(coordinate, city)}",
'neighbour_end': f"{GeometryHelper.coordinate_to_map_point(next_coordinate, city)}",
'coordinate_start': f"{GeometryHelper.coordinate_to_map_point(neighbour_info['line_start'], city)}",
'coordinate_end': f"{GeometryHelper.coordinate_to_map_point(neighbour_info['line_end'], city)}",
'shared_points': 1
}
@ -154,6 +167,8 @@ class GeometryHelper:
elif building not in neighbour.neighbours:
neighbour.neighbours.append(building)
line += 1
if plot:
img.show()
return lines_information
@staticmethod

View File

@ -6,7 +6,7 @@ log_dir = (Path(__file__).parent.parent / 'logs').resolve()
log_file = (log_dir / 'hub.log').resolve()
try:
if not os.path.isfile(log_file):
if not os.path.exists:
if not os.path.exists(log_dir):
os.mkdir(log_dir)
with open(log_file, 'x'):
pass

View File

@ -4,8 +4,10 @@ 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 math
import sys
from hub.hub_logger import logger
import hub.helpers.constants as cte
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
@ -37,10 +39,13 @@ class NrcanPhysicsParameters:
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:
logger.error(f'Building {building.name} has unknown construction archetype for building function: '
f'{building.function}, building year of construction: {building.year_of_construction} '
f'and climate zone {self._climate_zone}\n')
sys.stderr.write(f'Building {building.name} has unknown construction archetype for building function: '
f'{building.function}, building year of construction: {building.year_of_construction} '
f'and climate zone {self._climate_zone}\n')
return
continue
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
# one thermal zone per storey is assigned
if len(building.internal_zones) == 1:

View File

@ -39,14 +39,14 @@ class NrelPhysicsParameters:
archetype = self._search_archetype(nrel_catalog, function, building.year_of_construction,
self._climate_zone)
except KeyError:
logger.error(f'Building {building.name} has unknown archetype for building function: {building.function} '
f'and building year of construction: {building.year_of_construction} '
logger.error(f'Building {building.name} has unknown construction archetype for building function: '
f'{building.function} and building year of construction: {building.year_of_construction} '
f'and climate zone reference norm {self._climate_zone}\n')
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} '
f'and building year of construction: {building.year_of_construction} '
sys.stderr.write(f'Building {building.name} has unknown construction archetype for building function: '
f'{building.function} and building year of construction: {building.year_of_construction} '
f'and climate zone reference norm {self._climate_zone}\n')
return
continue
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
# one thermal zone per storey is assigned

View File

@ -6,13 +6,13 @@ Project Coder Guillermo Gutierrez Guillermo.GutierrezMorote@concordia.ca
"""
import json
import trimesh.creation
import numpy as np
from pyproj import Transformer
from shapely.geometry import Polygon as ShapelyPolygon
import hub.helpers.constants as cte
from hub.imports.geometry.helpers.geometry_helper import GeometryHelper
from hub.helpers.geometry_helper import GeometryHelper
from hub.imports.geometry.helpers.geometry_helper import GeometryHelper as igh
from hub.city_model_structure.attributes.polygon import Polygon
from hub.city_model_structure.building import Building
from hub.city_model_structure.building_demand.surface import Surface
@ -62,9 +62,12 @@ class Geojson:
surfaces = []
buildings = []
for zone, surface_coordinates in enumerate(surfaces_coordinates):
points = GeometryHelper.points_from_string(GeometryHelper.remove_last_point_from_string(surface_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)
surfaces.append(Surface(polygon, polygon, surface_type=cte.GROUND))
polygon.area = igh.ground_area(points)
surfaces.append(Surface(polygon, polygon))
buildings.append(Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function))
return buildings
@ -73,22 +76,41 @@ class Geojson:
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.surfaces:
shapely_polygon = ShapelyPolygon(surface.solid_polygon.coordinates)
if not shapely_polygon.is_valid:
print(surface.solid_polygon.area)
print('error?', name, surface_coordinates)
continue
mesh = trimesh.creation.extrude_polygon(shapely_polygon, height)
for face in mesh.faces:
points = []
for vertex_index in face:
points.append(mesh.vertices[vertex_index])
polygon = Polygon(points)
surface = Surface(polygon, polygon)
surfaces.append(surface)
buildings.append(Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function))
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)
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):
@ -106,6 +128,49 @@ class Geojson:
polygons.append(transformed_coordinates.lstrip(' '))
return polygons
@staticmethod
def _find_wall(line_1, line_2):
for i in range(0, 2):
j = 1 - i
point_1 = line_1[i]
point_2 = line_2[j]
distance = GeometryHelper.distance_between_points(point_1, point_2)
if distance > 1e-2:
return False
return True
def _store_shared_percentage_to_walls(self, city, city_mapped):
for building in city.buildings:
if building.name not in city_mapped.keys():
for wall in building.walls:
wall.percentage_shared = 0
continue
building_mapped = city_mapped[building.name]
for wall in building.walls:
percentage = 0
ground_line = []
for point in wall.perimeter_polygon.coordinates:
if point[2] < 0.5:
ground_line.append(point)
for entry in building_mapped:
if building_mapped[entry]['shared_points'] <= 3:
continue
line = [building_mapped[entry]['line_start'], building_mapped[entry]['line_end']]
neighbour_line = [building_mapped[entry]['neighbour_line_start'],
building_mapped[entry]['neighbour_line_end']]
neighbour_height = city.city_object(building_mapped[entry]['neighbour_name']).max_height
if self._find_wall(line, ground_line):
line_shared = (GeometryHelper.distance_between_points(line[0], line[1]) +
GeometryHelper.distance_between_points(neighbour_line[0], neighbour_line[1]) -
GeometryHelper.distance_between_points(line[1], neighbour_line[0]) -
GeometryHelper.distance_between_points(line[0], neighbour_line[1])) / 2
percentage_ground = line_shared / GeometryHelper.distance_between_points(line[0], line[1])
percentage_height = neighbour_height / building.max_height
if percentage_height > 1:
percentage_height = 1
percentage += percentage_ground * percentage_height
wall.percentage_shared = percentage
@property
def city(self) -> City:
"""
@ -115,6 +180,7 @@ class Geojson:
missing_functions = []
buildings = []
building_id = 0
lod = 1
for feature in self._geojson['features']:
extrusion_height = 0
if self._extrusion_height_field is not None:
@ -140,7 +206,6 @@ class Geojson:
building_name = f'building_{building_id}'
building_id += 1
polygons = []
lod = 1
for part, coordinates in enumerate(geometry['coordinates']):
polygons = self._get_polygons(polygons, coordinates)
for zone, polygon in enumerate(polygons):
@ -163,6 +228,9 @@ class Geojson:
for building in buildings:
self._city.add_city_object(building)
self._city.level_of_detail.geometry = lod
if lod == 1:
lines_information = GeometryHelper.city_mapping(self._city)
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

View File

@ -4,6 +4,8 @@ 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 math
import sys
import numpy as np
@ -45,3 +47,69 @@ class GeometryHelper:
array = points.split(' ')
res = " "
return res.join(array[0:len(array) - 3])
@staticmethod
def invert_points(points):
res = []
for point in points:
res.insert(0,point)
return res
@staticmethod
def ground_area(points):
"""
Get ground surface area in square meters
:return: float
"""
# New method to calculate area
if len(points) < 3:
sys.stderr.write('Warning: the area of a line or point cannot be calculated 1. Area = 0\n')
return 0
alpha = 0
vec_1 = points[1] - points[0]
for i in range(2, len(points)):
vec_2 = points[i] - points[0]
alpha += GeometryHelper.angle_between_vectors(vec_1, vec_2)
if alpha == 0:
sys.stderr.write('Warning: the area of a line or point cannot be calculated 2. Area = 0\n')
return 0
#
horizontal_points = points
area = 0
for i in range(0, len(horizontal_points) - 1):
point = horizontal_points[i]
next_point = horizontal_points[i + 1]
area += (next_point[1] + point[1]) / 2 * (next_point[0] - point[0])
next_point = horizontal_points[0]
point = horizontal_points[len(horizontal_points) - 1]
area += (next_point[1] + point[1]) / 2 * (next_point[0] - point[0])
_area = abs(area)
return _area
@staticmethod
def angle_between_vectors(vec_1, vec_2):
"""
angle between vectors in radians
:param vec_1: vector
:param vec_2: vector
:return: float
"""
if np.linalg.norm(vec_1) == 0 or np.linalg.norm(vec_2) == 0:
sys.stderr.write("Warning: impossible to calculate angle between planes' normal. Return 0\n")
return 0
cosine = np.dot(vec_1, vec_2) / np.linalg.norm(vec_1) / np.linalg.norm(vec_2)
if cosine > 1 and cosine - 1 < 1e-5:
cosine = 1
elif cosine < -1 and cosine + 1 > -1e-5:
cosine = -1
alpha = math.acos(cosine)
return alpha
@staticmethod
def invert_points(points):
res = []
for point in points:
res.insert(0,point)
return res

View File

@ -10,6 +10,7 @@ import pandas as pd
import csv
import hub.helpers.constants as cte
class InselMonthlyEnergyBalance:
"""
Import SRA results

View File

@ -8,6 +8,7 @@ import copy
import sys
import numpy
from hub.hub_logger import logger
import hub.helpers.constants as cte
from hub.helpers.dictionaries import Dictionaries
from hub.city_model_structure.building_demand.usage import Usage
@ -15,6 +16,7 @@ from hub.city_model_structure.building_demand.lighting import Lighting
from hub.city_model_structure.building_demand.occupancy import Occupancy
from hub.city_model_structure.building_demand.appliances import Appliances
from hub.city_model_structure.building_demand.thermal_control import ThermalControl
from hub.city_model_structure.building_demand.domestic_hot_water import DomesticHotWater
from hub.city_model_structure.attributes.schedule import Schedule
from hub.city_model_structure.building_demand.internal_gain import InternalGain
from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
@ -40,9 +42,9 @@ class ComnetUsageParameters:
try:
archetype_usage = self._search_archetypes(comnet_catalog, usage_name)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown usage archetype for building function:'
f' {building.function}')
return
logger.error(f'Building {building.name} has unknown usage archetype for usage: {usage_name}')
sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}')
continue
for internal_zone in building.internal_zones:
if internal_zone.area is None:
@ -54,7 +56,7 @@ class ComnetUsageParameters:
volume_per_area = internal_zone.volume / internal_zone.area
usage = Usage()
usage.name = usage_name
self._assign_values(usage, archetype_usage, volume_per_area)
self._assign_values(usage, archetype_usage, volume_per_area, building.cold_water_temperature)
usage.percentage = 1
self._calculate_reduced_values_from_extended_library(usage, archetype_usage)
@ -69,7 +71,7 @@ class ComnetUsageParameters:
raise KeyError('archetype not found')
@staticmethod
def _assign_values(usage, archetype, volume_per_area):
def _assign_values(usage, archetype, volume_per_area, cold_water_temperature):
# Due to the fact that python is not a typed language, the wrong object type is assigned to
# usage.occupancy when writing usage.occupancy = archetype.occupancy.
# Same happens for lighting and appliances. Therefore, this walk around has been done.
@ -101,6 +103,17 @@ class ComnetUsageParameters:
_control.heating_set_point_schedules = archetype.thermal_control.heating_set_point_schedules
_control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules
usage.thermal_control = _control
_domestic_hot_water = DomesticHotWater()
_domestic_hot_water.density = archetype.domestic_hot_water.density
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
cold_temperature = cold_water_temperature[cte.YEAR]['epw']
peak_flow = 0
if (archetype.domestic_hot_water.service_temperature - cold_temperature) > 0:
peak_flow = archetype.domestic_hot_water.density / cte.WATER_DENSITY / cte.WATER_HEAT_CAPACITY \
/ (archetype.domestic_hot_water.service_temperature - cold_temperature)
_domestic_hot_water.peak_flow = peak_flow
_domestic_hot_water.schedules = archetype.domestic_hot_water.schedules
usage.domestic_hot_water = _domestic_hot_water
@staticmethod
def _calculate_reduced_values_from_extended_library(usage, archetype):

View File

@ -7,6 +7,7 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
import sys
from hub.hub_logger import logger
import hub.helpers.constants as cte
from hub.helpers.dictionaries import Dictionaries
from hub.city_model_structure.building_demand.usage import Usage
@ -14,6 +15,7 @@ from hub.city_model_structure.building_demand.lighting import Lighting
from hub.city_model_structure.building_demand.occupancy import Occupancy
from hub.city_model_structure.building_demand.appliances import Appliances
from hub.city_model_structure.building_demand.thermal_control import ThermalControl
from hub.city_model_structure.building_demand.domestic_hot_water import DomesticHotWater
from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
@ -39,17 +41,17 @@ class NrcanUsageParameters:
try:
archetype_usage = self._search_archetypes(nrcan_catalog, usage_name)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown usage archetype for building function:'
f' {building.function}')
return
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')
continue
usage_name = Dictionaries().hub_usage_to_comnet_usage[building.function]
try:
comnet_archetype_usage = self._search_archetypes(comnet_catalog, usage_name)
except KeyError:
sys.stderr.write(f'Building {building.name} has unknown usage archetype for building function:'
f' {building.function}')
return
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')
continue
for internal_zone in building.internal_zones:
if internal_zone.area is None:
@ -61,7 +63,7 @@ class NrcanUsageParameters:
volume_per_area = internal_zone.volume / internal_zone.area
usage = Usage()
usage.name = usage_name
self._assign_values(usage, archetype_usage, volume_per_area)
self._assign_values(usage, archetype_usage, volume_per_area, building.cold_water_temperature)
self._assign_comnet_extra_values(usage, comnet_archetype_usage)
usage.percentage = 1
self._calculate_reduced_values_from_extended_library(usage, archetype_usage)
@ -77,7 +79,7 @@ class NrcanUsageParameters:
raise KeyError('archetype not found')
@staticmethod
def _assign_values(usage, archetype, volume_per_area):
def _assign_values(usage, archetype, volume_per_area, cold_water_temperature):
if archetype.mechanical_air_change > 0:
usage.mechanical_air_change = archetype.mechanical_air_change
elif archetype.ventilation_rate > 0:
@ -111,6 +113,14 @@ class NrcanUsageParameters:
_control.heating_set_point_schedules = archetype.thermal_control.heating_set_point_schedules
_control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules
usage.thermal_control = _control
_domestic_hot_water = DomesticHotWater()
_domestic_hot_water.peak_flow = archetype.domestic_hot_water.peak_flow
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
cold_temperature = cold_water_temperature[cte.YEAR]['epw']
_domestic_hot_water.density = archetype.domestic_hot_water.peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY \
* (archetype.domestic_hot_water.service_temperature - cold_temperature)
_domestic_hot_water.schedules = archetype.domestic_hot_water.schedules
usage.domestic_hot_water = _domestic_hot_water
@staticmethod
def _assign_comnet_extra_values(usage, archetype):

View File

@ -32,14 +32,13 @@ class EpwWeatherParameters:
_ = file.readline().split(',')
line = file.readline().split(',')
number_records = int(line[1])
depth_measurement_ground_temperature = []
ground_temperature = []
ground_temperature = {}
for i in range(0, number_records):
depth_measurement_ground_temperature.append(line[i*16+2])
depth_measurement_ground_temperature = line[i*16+2]
temperatures = []
for j in range(0, 12):
temperatures.append(line[i*16+j+6])
ground_temperature.append(temperatures)
ground_temperature[depth_measurement_ground_temperature] = temperatures
file.close()
except SystemExit:
sys.stderr.write(f'Error: weather file {self._path} not found. Please download it from '
@ -74,6 +73,7 @@ class EpwWeatherParameters:
sys.exit()
for building in self._city.buildings:
building.ground_temperature[cte.MONTH] = ground_temperature
if cte.HOUR in building.external_temperature:
del building.external_temperature[cte.HOUR]
new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw'])
@ -111,10 +111,24 @@ class EpwWeatherParameters:
building.beam[cte.HOUR] = new_value
else:
pd.concat([building.beam[cte.HOUR], new_value], axis=1)
new_value = wh().cold_water_temperature(building.external_temperature[cte.HOUR]['epw'])
if cte.HOUR not in building.cold_water_temperature:
building.cold_water_temperature[cte.HOUR] = new_value
else:
pd.concat([building.cold_water_temperature[cte.HOUR], new_value], axis=1)
# create the monthly and yearly values out of the hourly
for building in self._city.buildings:
if cte.MONTH not in building.external_temperature:
building.external_temperature[cte.MONTH] = wh().get_monthly_mean_values(building.external_temperature[cte.HOUR][['epw']])
building.external_temperature[cte.MONTH] = \
wh().get_monthly_mean_values(building.external_temperature[cte.HOUR][['epw']])
if cte.YEAR not in building.external_temperature:
building.external_temperature[cte.YEAR] = wh(). get_yearly_mean_values(building.external_temperature[cte.HOUR][['epw']])
building.external_temperature[cte.YEAR] = \
wh(). get_yearly_mean_values(building.external_temperature[cte.HOUR][['epw']])
if cte.MONTH not in building.cold_water_temperature:
building.cold_water_temperature[cte.MONTH] = wh().get_monthly_mean_values(
building.cold_water_temperature[cte.HOUR][['epw']])
if cte.YEAR not in building.cold_water_temperature:
building.cold_water_temperature[cte.YEAR] = wh().get_yearly_mean_values(
building.cold_water_temperature[cte.HOUR][['epw']])
self._city.level_of_detail.weather = 2

View File

@ -4,6 +4,7 @@ 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 math
import hub.helpers.constants as cte
import pandas as pd
@ -20,7 +21,7 @@ class Weather:
def sky_temperature(ambient_temperature):
"""
Get sky temperature from ambient temperature in Celsius
:return: float
:return: List[float]
"""
# Swinbank - Source sky model approximation(1963) based on cloudiness statistics(32 %) in United States
# ambient temperatures( in °C)
@ -32,6 +33,37 @@ class Weather:
values.append(value)
return values
@staticmethod
def cold_water_temperature(ambient_temperature):
"""
Get cold water temperature from ambient temperature in Celsius
:return: dict
"""
# Equation from "TOWARDS DEVELOPMENT OF AN ALGORITHM FOR MAINS WATER TEMPERATURE", 2004, Jay Burch
# and Craig Christensen, National Renewable Energy Laboratory
# ambient temperatures( in °C)
# cold water temperatures( in °C)
ambient_temperature_fahrenheit = []
average_temperature = 0
maximum_temperature = -1000
minimum_temperature = 1000
for temperature in ambient_temperature:
value = temperature * 9 / 5 + 32
ambient_temperature_fahrenheit.append(value)
average_temperature += value / 8760
if value > maximum_temperature:
maximum_temperature = value
if value < minimum_temperature:
minimum_temperature = value
delta_temperature = maximum_temperature - minimum_temperature
ratio = 0.4 + 0.01 * (average_temperature - 44)
lag = 35 - 1 * (average_temperature - 44)
cold_temperature = []
for temperature in ambient_temperature_fahrenheit:
radians = (0.986 * (temperature-15-lag) - 90) * math.pi / 180
cold_temperature.append((average_temperature + 6 + ratio * (delta_temperature/2) * math.sin(radians) - 32) * 5/9)
return pd.DataFrame(cold_temperature, columns=['epw'])
def get_monthly_mean_values(self, values):
out = None
if values is not None:
@ -41,7 +73,8 @@ class Weather:
del out['month']
return out
def get_yearly_mean_values(self, values):
@staticmethod
def get_yearly_mean_values(values):
return values.mean()
def get_total_month(self, values):

View File

@ -121,7 +121,24 @@ class City(Repository):
result_set = self.session.execute(select(Model).where(Model.user_id == user_id,
Model.application_id == application_id,
Model.name == city_name
)).first()[0]
)).first()
if result_set is not None:
result_set = result_set[0]
return result_set
except SQLAlchemyError as err:
logger.error(f'Error while fetching city by name: {err}')
def get_by_user_id_and_application_id(self, user_id, application_id) -> [Model]:
"""
Fetch city based on the user who created it
:param user_id: the user id
:param application_id: the application id
:return: ModelCity
"""
try:
result_set = self.session.execute(
select(Model).where(Model.user_id == user_id, Model.application_id == application_id)
)
return [r[0] for r in result_set]
except SQLAlchemyError as err:
logger.error(f'Error while fetching city by name: {err}')

View File

@ -105,7 +105,7 @@ class CityObject(Repository):
except SQLAlchemyError as err:
logger.error(f'Error while deleting application: {err}')
def get_by_name_and_city(self, name, city_id) -> [Model]:
def get_by_name_and_city(self, name, city_id) -> Union[Model, None]:
"""
Fetch a city object based on name and city id
:param name: city object name

View File

@ -10,6 +10,7 @@ from typing import Union, Dict
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy import or_
from hub.hub_logger import logger
from hub.persistence import Repository
@ -98,7 +99,7 @@ class SimulationResults(Repository):
Deletes an application with the application_uuid
:param name: The simulation results tool and workflow name
:param city_id: The id for the city owning the simulation results
:param city_object_id: the id for the city_object ownning these simulation results
:param city_object_id: the id for the city_object owning these simulation results
:return: None
"""
@ -125,28 +126,6 @@ class SimulationResults(Repository):
except SQLAlchemyError as err:
logger.error(f'Error while fetching city by city_id: {err}')
def get_simulation_results_by_city_id(self, city_id) -> [Model]:
"""
Fetch simulation results by name
:param city_id: the id of the city
:return: [Model] with the provided city id
"""
try:
return self.session.execute(select(Model).where(Model.city_id == city_id))
except SQLAlchemyError as err:
logger.error(f'Error while fetching simulation results by name: {err}')
def get_simulation_results_by_city_object_id(self, city_object_id) -> [Model]:
"""
Fetch simulation results by name
:param city_object_id: the id of the city object
:return: [Model] with the provided city object id
"""
try:
return self.session.execute(select(Model).where(Model.city_object_id == city_object_id))
except SQLAlchemyError as err:
logger.error(f'Error while fetching simulation results by name: {err}')
def _get_city_object(self, city_object_id) -> [CityObject]:
"""
Fetch a city object based city id
@ -157,3 +136,27 @@ class SimulationResults(Repository):
return self.session.execute(select(CityObject).where(CityObject.id == city_object_id)).first()
except SQLAlchemyError as err:
logger.error(f'Error while fetching city by city_id: {err}')
def get_simulation_results_by_city_id_city_object_id_and_names(self, city_id, city_object_id, result_names=[]):
"""
Fetch the simulation results based in the city_id or city_object_id with the given names or all
:param city_id: the city id
:param city_object_id: the city object id
:param result_names: if given filter the results
:return: [SimulationResult]
"""
try:
result_set = self.session.execute(select(Model).where(or_(
Model.city_id == city_id,
Model.city_object_id == city_object_id
)))
results = [r[0] for r in result_set]
if not result_names:
return results
_ = []
for result in results:
if result.name in result_names:
_.append(result)
return _
except SQLAlchemyError as err:
logger.error(f'Error while fetching city by city_id: {err}')

View File

@ -60,7 +60,7 @@ class User(Repository):
:param name: the name of the user
:param password: the password of the user
:param role: the role of the user
:return:
:return: None, Dictionary
"""
try:
self.session.query(Model).filter(Model.id == user_id).update({
@ -86,28 +86,30 @@ class User(Repository):
except SQLAlchemyError as err:
logger.error(f'Error while fetching user: {err}')
def get_by_name_and_application(self, name: str, application_id: int) -> [Model]:
def get_by_name_and_application(self, name: str, application_id: int) -> Union[Model, None]:
"""
Fetch user based on the email address
:param name: User name
:param application_id: User application name
:return: [User] matching the search criteria
:return: User matching the search criteria or None
"""
try:
return self.session.execute(
user = self.session.execute(
select(Model).where(Model.name == name, Model.application_id == application_id)
).first()
if user is not None:
user = user[0]
return user
except SQLAlchemyError as err:
logger.error(f'Error while fetching user by name and application: {err}')
def get_by_name_application_id_and_password(self, name: str, password: str, application_id: int) -> [Model]:
def get_by_name_application_id_and_password(self, name: str, password: str, application_id: int) -> Union[Model, None]:
"""
Fetch user based on the email and password
:param name: User name
:param password: User password
:param application_id: User password
:return: [User]
:return: User
"""
try:
user = self.session.execute(
@ -119,14 +121,13 @@ class User(Repository):
except SQLAlchemyError as err:
logger.error(f'Error while fetching user by email: {err}')
def get_by_name_application_uuid_and_password(self, name: str, password: str, application_uuid: str) -> [Model]:
def get_by_name_application_uuid_and_password(self, name: str, password: str, application_uuid: str) -> Union[Model, None]:
"""
Fetch user based on the email and password
:param name: User name
:param password: User password
:param application_uuid: Application uuid
:return: [User]
:return: User
"""
try:
application = self.session.execute(

View File

@ -23,3 +23,4 @@ shapely
geopandas
triangle
psycopg2-binary
PIL

View File

@ -71,8 +71,6 @@ class TestExports(TestCase):
self._complete_city = self._get_complete_city(from_pickle)
EnergyBuildingsExportsFactory(export_type, self._complete_city, self._output_path).export()
def test_obj_export(self):
"""
export to obj

View File

@ -118,7 +118,6 @@ class TestGeometryFactory(TestCase):
city = self._get_city(file, 'rhino')
self.assertIsNotNone(city, 'city is none')
self.assertTrue(len(city.buildings) == 36)
i = 0
def test_import_obj(self):
"""
@ -135,14 +134,19 @@ class TestGeometryFactory(TestCase):
"""
Test geojson import
"""
file = 'concordia.geojson'
file = '2000_buildings.geojson'
start = datetime.datetime.now()
city = self._get_city(file, 'geojson',
height_field='citygml_me',
height_field='building_height',
year_of_construction_field='ANNEE_CONS',
function_field='CODE_UTILI')
end = datetime.datetime.now()
print(f'geometry load in {end-start} s')
start = datetime.datetime.now()
hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export()
self.assertEqual(207, len(city.buildings), 'wrong number of buildings')
end = datetime.datetime.now()
print(f'geometry export in {end - start} s')
self.assertEqual(2356, len(city.buildings), 'wrong number of buildings')
self._check_buildings(city)
def test_map_neighbours(self):
@ -154,7 +158,13 @@ class TestGeometryFactory(TestCase):
height_field='citygml_me',
year_of_construction_field='ANNEE_CONS',
function_field='LIBELLE_UT')
GeometryHelper.city_mapping(city)
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))
@ -164,4 +174,3 @@ class TestGeometryFactory(TestCase):
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)

View File

@ -124,3 +124,7 @@ class TestUsageFactory(TestCase):
self.assertIsNotNone(appliances.schedules, 'appliances schedule is none')
self.assertIsNotNone(usage.thermal_control.hvac_availability_schedules,
'control hvac availability is none')
self.assertIsNotNone(usage.domestic_hot_water.density, 'domestic hot water density is none')
self.assertIsNotNone(usage.domestic_hot_water.service_temperature,
'domestic hot water service temperature is none')
self.assertIsNotNone(usage.domestic_hot_water.schedules, 'domestic hot water schedules is none')

File diff suppressed because one or more lines are too long

View File

@ -12,18 +12,18 @@
-73.580414175680588,
45.497641136608358
],
[
-73.581414175680588,
45.497641136608358
],
[
-73.581414175680588,
45.498641136608358
],
[
-73.580414175680588,
45.498641136608358
],
[
-73.581414175680588,
45.498641136608358
],
[
-73.581414175680588,
45.497641136608358
],
[
-73.580414175680588,
45.497641136608358
@ -204,19 +204,20 @@
[
-73.581414175680588,
45.497641136608358
]
,
[
-73.581414175680588,
45.498441136608358
],
[
-73.582214175680588,
45.498441136608358
],
[
-73.582214175680588,
45.497641136608358
],
[
-73.582214175680588,
45.498441136608358
],
[
-73.581414175680588,
45.498441136608358
],
[
-73.581414175680588,
45.497641136608358
@ -399,31 +400,30 @@
-73.581914175680588,
45.498441136608358
],
[
-73.581914175680588,
45.499641136608358
],
[
-73.580914175680588,
45.499641136608358
],
[
-73.580914175680588,
45.498641136608358
],
[
-73.581414175680588,
45.498641136608358
],
[
-73.581414175680588,
45.498441136608358
],
[
-73.581414175680588,
45.498641136608358
],
[
-73.580914175680588,
45.498641136608358
],
[
-73.580914175680588,
45.499641136608358
],
[
-73.581914175680588,
45.499641136608358
],
[
-73.581914175680588,
45.498441136608358
]
]
]
},

View File

@ -1 +1 @@
__version__ = '0.1.7.8'
__version__ = '0.1.7.10'