meb_debugging #8

Merged
g_gutierrez merged 15 commits from meb_debugging into main 2023-03-20 14:21:25 -04:00
40 changed files with 1265 additions and 893 deletions

View File

@ -8,12 +8,13 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
class Catalog: 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): 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 :return: Catalog names filter by category if provided
""" """
raise NotImplementedError raise NotImplementedError

View File

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

View File

@ -1,8 +1,8 @@
""" """
Archetype catalog Cost Archetype catalog Cost
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2023 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost 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: 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._function = function
self._municipality = municipality self._municipality = municipality
self._country = country
self._currency = currency self._currency = currency
self._capital_cost = capital_cost self._capital_cost = capital_cost
self._operational_cost = operational_cost self._operational_cost = operational_cost
@ -26,7 +38,15 @@ class Archetype:
Get name Get name
:return: string :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 @property
def function(self): def function(self):
@ -44,6 +64,14 @@ class Archetype:
""" """
return self._municipality return self._municipality
@property
def country(self):
"""
Get country
:return: string
"""
return self._country
@property @property
def currency(self): 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 SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2023 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from hub.catalog_factories.data_models.cost.envelope import Envelope from typing import List
from hub.catalog_factories.data_models.cost.systems import Systems from hub.catalog_factories.data_models.cost.chapter import Chapter
class CapitalCost: class CapitalCost:
def __init__(self, structural, sub_structural, envelope, systems, surface_finish, engineer): def __init__(self, general_chapters, design_allowance, overhead_and_profit):
self._structural = structural self._general_chapters = general_chapters
self._sub_structural = sub_structural self._design_allowance = design_allowance
self._envelope = envelope self._overhead_and_profit = overhead_and_profit
self._systems = systems
self._surface_finish = surface_finish
self._engineer = engineer
@property @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: float
""" """
return self._structural return self._design_allowance
@property @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: float
""" """
return self._sub_structural return self._overhead_and_profit
@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

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

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 SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2023 Concordia CERC group
Project Coder Atiya atiya.atiya@mail.concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
Code contributors: 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: class OperationalCost:
def __init__(self, fuel_type, fuel_fixed_operational_monthly, fuel_fixed_operational_peak, def __init__(self, fuels, maintenance_heating, maintenance_cooling, maintenance_pv, co2):
fuel_variable_operational, heating_equipment_maintenance, cooling_equipment_maintenance, self._fuels = fuels
general_hvac_equipment_maintenance, photovoltaic_system_maintenance, other_systems_maintenance, self._maintenance_heating = maintenance_heating
co2_emissions): self._maintenance_cooling = maintenance_cooling
self._fuel_type = fuel_type self._maintenance_pv = maintenance_pv
self._fuel_fixed_operational_monthly = fuel_fixed_operational_monthly self._co2 = co2
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
@property @property
def fuel_type(self): def fuels(self) -> List[Fuel]:
""" """
Get fuel type Get fuels listed in capital costs
:return: string :return: [FUEL]
""" """
return self._fuel_type return self._fuels
@property @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: float
""" """
return self._fuel_fixed_operational_monthly return self._maintenance_heating
@property @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: float
""" """
return self._fuel_fixed_operational_peak return self._maintenance_cooling
@property @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: float
""" """
return self._fuel_variable_operational return self._maintenance_pv
@property @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: float
""" """
return self._heating_equipment_maintenance return self._co2
@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

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.lighting import Lighting
from hub.catalog_factories.data_models.usages.ocupancy import Occupancy 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.thermal_control import ThermalControl
from hub.catalog_factories.data_models.usages.domestic_hot_water import DomesticHotWater
class Usage: class Usage:
@ -21,7 +22,8 @@ class Usage:
occupancy, occupancy,
lighting, lighting,
appliances, appliances,
thermal_control): thermal_control,
domestic_hot_water):
self._name = name self._name = name
self._hours_day = hours_day self._hours_day = hours_day
self._days_year = days_year self._days_year = days_year
@ -32,6 +34,7 @@ class Usage:
self._lighting = lighting self._lighting = lighting
self._appliances = appliances self._appliances = appliances
self._thermal_control = thermal_control self._thermal_control = thermal_control
self._domestic_hot_water = domestic_hot_water
@property @property
def name(self) -> Union[None, str]: def name(self) -> Union[None, str]:
@ -108,7 +111,15 @@ class Usage:
@property @property
def thermal_control(self) -> Union[None, ThermalControl]: def thermal_control(self) -> Union[None, ThermalControl]:
""" """
Get thermal control of this thermal zone Get thermal control information
:return: None or ThermalControl :return: None or ThermalControl
""" """
return self._thermal_control 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.content import Content
from hub.catalog_factories.data_models.usages.lighting import Lighting 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.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.schedule import Schedule
from hub.catalog_factories.data_models.usages.thermal_control import ThermalControl 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.data_models.usages.usage import Usage
@ -51,6 +52,7 @@ class ComnetCatalog(Catalog):
ventilation_rate = self._archetypes['ventilation rate'][comnet_usage] ventilation_rate = self._archetypes['ventilation rate'][comnet_usage]
# convert cfm/ft2 to m3/m2.s # convert cfm/ft2 to m3/m2.s
ventilation_rate = ventilation_rate / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS) ventilation_rate = ventilation_rate / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
domestic_hot_water_archetype = self._archetypes['water heating'][comnet_usage]
# get occupancy # get occupancy
occupancy_density = occupancy_archetype[0] / pow(cte.METERS_TO_FEET, 2) occupancy_density = occupancy_archetype[0] / pow(cte.METERS_TO_FEET, 2)
@ -96,6 +98,16 @@ class ComnetCatalog(Catalog):
self._schedules[schedule_name]['ClgSetPt'] 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, usages.append(Usage(comnet_usage,
hours_day, hours_day,
days_year, days_year,
@ -104,7 +116,8 @@ class ComnetCatalog(Catalog):
occupancy, occupancy,
lighting, lighting,
appliances, appliances,
thermal_control)) thermal_control,
domestic_hot_water))
self._content = Content(usages) 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_values[day] = _extracted_data.iloc[start:end, 3:27].to_numpy().tolist()[0]
_schedule = [] _schedule = []
for day in _schedule_values: 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 # to celsius
if 'n.a.' in _schedule_values[day]: if 'n.a.' in _schedule_values[day]:
_schedule_values[day] = None _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.content import Content
from hub.catalog_factories.data_models.usages.lighting import Lighting 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.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.schedule import Schedule
from hub.catalog_factories.data_models.usages.thermal_control import ThermalControl 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.data_models.usages.usage import Usage
@ -36,7 +37,7 @@ class NrcanCatalog(Catalog):
@staticmethod @staticmethod
def _extract_schedule(raw): def _extract_schedule(raw):
nrcan_schedule_type = raw['category'] 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' nrcan_schedule_type = f'{nrcan_schedule_type} Heating'
elif 'Cooling' in raw['name']: elif 'Cooling' in raw['name']:
nrcan_schedule_type = f'{nrcan_schedule_type} Cooling' 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] 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']] data_type = UsageHelper().nrcan_data_type_to_hub_data_type[raw['units']]
time_step = UsageHelper().nrcan_time_to_hub_time[raw['type']] time_step = UsageHelper().nrcan_time_to_hub_time[raw['type']]
# nrcan only uses yearly range for the schedules # nrcan only uses daily range for the schedules
time_range = cte.YEAR time_range = cte.DAY
day_types = UsageHelper().nrcan_day_type_to_hub_days[raw['day_types']] 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) 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"]}' url = f'{self._base_url}{name["space_types_location"]}'
with urllib.request.urlopen(url) as json_file: with urllib.request.urlopen(url) as json_file:
space_types = json.load(json_file)['tables']['space_types']['table'] 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'] space_types = [st for st in space_types if st['space_type'] == 'WholeBuilding']
for space_type in space_types: for space_type in space_types:
# usage_type = space_type['space_type']
usage_type = space_type['building_type'] usage_type = space_type['building_type']
occupancy_schedule_name = space_type['occupancy_schedule'] occupancy_schedule_name = space_type['occupancy_schedule']
lighting_schedule_name = space_type['lighting_schedule'] lighting_schedule_name = space_type['lighting_schedule']
@ -91,12 +90,14 @@ class NrcanCatalog(Catalog):
hvac_schedule_name = hvac_schedule_name.replace('FAN', 'Fan') hvac_schedule_name = hvac_schedule_name.replace('FAN', 'Fan')
heating_setpoint_schedule_name = space_type['heating_setpoint_schedule'] heating_setpoint_schedule_name = space_type['heating_setpoint_schedule']
cooling_setpoint_schedule_name = space_type['cooling_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) occupancy_schedule = self._get_schedules(occupancy_schedule_name)
lighting_schedule = self._get_schedules(lighting_schedule_name) lighting_schedule = self._get_schedules(lighting_schedule_name)
appliance_schedule = self._get_schedules(appliance_schedule_name) appliance_schedule = self._get_schedules(appliance_schedule_name)
heating_schedule = self._get_schedules(heating_setpoint_schedule_name) heating_schedule = self._get_schedules(heating_setpoint_schedule_name)
cooling_schedule = self._get_schedules(cooling_setpoint_schedule_name) cooling_schedule = self._get_schedules(cooling_setpoint_schedule_name)
hvac_availability = self._get_schedules(hvac_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'] 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: if appliances_radiative_fraction is not None and appliances_latent_fraction is not None:
appliances_convective_fraction = 1 - appliances_radiative_fraction - appliances_latent_fraction 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, occupancy = Occupancy(occupancy_density,
None, None,
None, None,
@ -145,6 +151,11 @@ class NrcanCatalog(Catalog):
hvac_availability, hvac_availability,
heating_schedule, heating_schedule,
cooling_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 hours_day = None
days_year = None days_year = None
usages.append(Usage(usage_type, usages.append(Usage(usage_type,
@ -155,7 +166,8 @@ class NrcanCatalog(Catalog):
occupancy, occupancy,
lighting, lighting,
appliances, appliances,
thermal_control)) thermal_control,
domestic_hot_water))
return usages return usages
def names(self, category=None): def names(self, category=None):

View File

@ -19,7 +19,8 @@ class UsageHelper:
'Equipment': cte.APPLIANCES, 'Equipment': cte.APPLIANCES,
'Thermostat Setpoint Cooling': cte.COOLING_SET_POINT, # Compose 'Thermostat Setpoint' + 'Cooling' 'Thermostat Setpoint Cooling': cte.COOLING_SET_POINT, # Compose 'Thermostat Setpoint' + 'Cooling'
'Thermostat Setpoint Heating': cte.HEATING_SET_POINT, # Compose 'Thermostat Setpoint' + 'Heating' '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 = { _nrcan_data_type_to_hub_data_type = {
'FRACTION': cte.FRACTION, 'FRACTION': cte.FRACTION,

View File

@ -38,6 +38,7 @@ class Building(CityObject):
self._shell = None self._shell = None
self._alias = None self._alias = None
self._type = 'building' self._type = 'building'
self._cold_water_temperature = dict()
self._heating = dict() self._heating = dict()
self._cooling = dict() self._cooling = dict()
self._lighting_electrical_demand = dict() self._lighting_electrical_demand = dict()
@ -265,6 +266,22 @@ class Building(CityObject):
if value is not None: if value is not None:
self._storeys_above_ground = int(value) 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 @property
def heating(self) -> dict: 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.lighting import Lighting
from hub.city_model_structure.building_demand.internal_gain import InternalGain 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.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.attributes.schedule import Schedule
import hub.helpers.constants as cte import hub.helpers.constants as cte
@ -53,6 +54,7 @@ class ThermalZone:
self._appliances = None self._appliances = None
self._internal_gains = None self._internal_gains = None
self._thermal_control = None self._thermal_control = None
self._domestic_hot_water = None
self._usages = None self._usages = None
@property @property
@ -590,6 +592,46 @@ class ThermalZone:
return self._thermal_control 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 @property
def total_floor_area(self): 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.lighting import Lighting
from hub.city_model_structure.building_demand.appliances import Appliances 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.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 from hub.city_model_structure.building_demand.internal_gain import InternalGain
@ -31,6 +32,7 @@ class Usage:
self._lighting = None self._lighting = None
self._appliances = None self._appliances = None
self._thermal_control = None self._thermal_control = None
self._domestic_hot_water = None
@property @property
def id(self): def id(self):
@ -236,7 +238,7 @@ class Usage:
@property @property
def thermal_control(self) -> Union[None, ThermalControl]: def thermal_control(self) -> Union[None, ThermalControl]:
""" """
Get thermal control of this thermal zone Get thermal control information
:return: None or ThermalControl :return: None or ThermalControl
""" """
return self._thermal_control return self._thermal_control
@ -244,7 +246,23 @@ class Usage:
@thermal_control.setter @thermal_control.setter
def thermal_control(self, value): def thermal_control(self, value):
""" """
Set thermal control for this thermal zone Set thermal control information
:param value: ThermalControl :param value: ThermalControl
""" """
self._thermal_control = value 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

@ -36,6 +36,7 @@ class CityObject:
self._centroid = None self._centroid = None
self._volume = None self._volume = None
self._external_temperature = dict() self._external_temperature = dict()
self._ground_temperature = dict()
self._global_horizontal = dict() self._global_horizontal = dict()
self._diffuse = dict() self._diffuse = dict()
self._beam = dict() self._beam = dict()
@ -165,6 +166,24 @@ class CityObject:
""" """
self._external_temperature = value 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 @property
def global_horizontal(self) -> dict: def global_horizontal(self) -> dict:
""" """

View File

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

View File

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

@ -17,14 +17,6 @@ class ConfigurationHelper:
self._config = configparser.ConfigParser() self._config = configparser.ConfigParser()
self._config.read(config_file) 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 @property
def min_coordinate(self) -> float: def min_coordinate(self) -> float:
""" """
@ -146,3 +138,11 @@ class ConfigurationHelper:
:return: 0.3 :return: 0.3
""" """
return self._config.getfloat('buildings', 'short_wave_reflectance').real 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 # universal constants
KELVIN = 273.15 KELVIN = 273.15
WATER_DENSITY = 1000
WATER_HEAT_CAPACITY = 4182
# converters # converters
HOUR_TO_MINUTES = 60 HOUR_TO_MINUTES = 60
MINUTES_TO_SECONDS = 60 MINUTES_TO_SECONDS = 60
HOUR_TO_SECONDS = 3600
METERS_TO_FEET = 3.28084 METERS_TO_FEET = 3.28084
BTU_H_TO_WATTS = 0.29307107 BTU_H_TO_WATTS = 0.29307107
KILO_WATTS_HOUR_TO_JULES = 3600000 KILO_WATTS_HOUR_TO_JULES = 3600000
GALLONS_TO_QUBIC_METERS = 0.0037854117954011185
# time # time
SECOND = 'second' SECOND = 'second'
@ -137,6 +141,7 @@ HEATING_SET_POINT = 'HtgSetPt'
EQUIPMENT = 'Equipment' EQUIPMENT = 'Equipment'
ACTIVITY = 'Activity' ACTIVITY = 'Activity'
PEOPLE_ACTIVITY_LEVEL = 'People Activity Level' PEOPLE_ACTIVITY_LEVEL = 'People Activity Level'
DOMESTIC_HOT_WATER = 'Domestic Hot Water'
# Geometry # Geometry
EPSILON = 0.0000001 EPSILON = 0.0000001
@ -157,3 +162,19 @@ MIN_FLOAT = float('-inf')
# Tools # Tools
SRA = 'sra' SRA = 'sra'
INSEL_MEB = 'insel meb' 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

@ -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_hft_usage import HubUsageToHftUsage
from hub.helpers.data.hub_usage_to_nrcan_usage import HubUsageToNrcanUsage from hub.helpers.data.hub_usage_to_nrcan_usage import HubUsageToNrcanUsage
class Dictionaries: class Dictionaries:
""" """
Dictionaries class Dictionaries class

View File

@ -7,10 +7,8 @@ Project Coder Guillermo Gutierrez Guillermo.GutierrezMorote@concordia.ca
import json import json
import numpy as np import numpy as np
import trimesh.creation
from pyproj import Transformer from pyproj import Transformer
from shapely.geometry import Polygon as ShapelyPolygon
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.helpers.geometry_helper import GeometryHelper from hub.helpers.geometry_helper import GeometryHelper
@ -133,8 +131,9 @@ class Geojson:
@staticmethod @staticmethod
def _find_wall(line_1, line_2): def _find_wall(line_1, line_2):
for i in range(0, 2): for i in range(0, 2):
j = 1 - i
point_1 = line_1[i] point_1 = line_1[i]
point_2 = line_2[i] point_2 = line_2[j]
distance = GeometryHelper.distance_between_points(point_1, point_2) distance = GeometryHelper.distance_between_points(point_1, point_2)
if distance > 1e-2: if distance > 1e-2:
return False return False
@ -143,6 +142,8 @@ class Geojson:
def _store_shared_percentage_to_walls(self, city, city_mapped): def _store_shared_percentage_to_walls(self, city, city_mapped):
for building in city.buildings: for building in city.buildings:
if building.name not in city_mapped.keys(): if building.name not in city_mapped.keys():
for wall in building.walls:
wall.percentage_shared = 0
continue continue
building_mapped = city_mapped[building.name] building_mapped = city_mapped[building.name]
for wall in building.walls: for wall in building.walls:
@ -151,12 +152,8 @@ class Geojson:
for point in wall.perimeter_polygon.coordinates: for point in wall.perimeter_polygon.coordinates:
if point[2] < 0.5: if point[2] < 0.5:
ground_line.append(point) ground_line.append(point)
# todo: erase when we have no triangulation
if len(ground_line) < 2:
continue
# todo: erase down to here
for entry in building_mapped: for entry in building_mapped:
if building_mapped[entry]['shared_points'] <= 5: if building_mapped[entry]['shared_points'] <= 3:
continue continue
line = [building_mapped[entry]['line_start'], building_mapped[entry]['line_end']] line = [building_mapped[entry]['line_start'], building_mapped[entry]['line_end']]
neighbour_line = [building_mapped[entry]['neighbour_line_start'], neighbour_line = [building_mapped[entry]['neighbour_line_start'],

View File

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

View File

@ -8,6 +8,7 @@ import copy
import sys import sys
import numpy import numpy
from hub.hub_logger import logger
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.helpers.dictionaries import Dictionaries from hub.helpers.dictionaries import Dictionaries
from hub.city_model_structure.building_demand.usage import Usage 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.occupancy import Occupancy
from hub.city_model_structure.building_demand.appliances import Appliances 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.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.attributes.schedule import Schedule
from hub.city_model_structure.building_demand.internal_gain import InternalGain from hub.city_model_structure.building_demand.internal_gain import InternalGain
from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
@ -40,8 +42,8 @@ class ComnetUsageParameters:
try: try:
archetype_usage = self._search_archetypes(comnet_catalog, usage_name) archetype_usage = self._search_archetypes(comnet_catalog, usage_name)
except KeyError: except KeyError:
sys.stderr.write(f'Building {building.name} has unknown usage archetype for building function:' logger.error(f'Building {building.name} has unknown usage archetype for usage: {usage_name}')
f' {building.function}') sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}')
continue continue
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
@ -54,7 +56,7 @@ class ComnetUsageParameters:
volume_per_area = internal_zone.volume / internal_zone.area volume_per_area = internal_zone.volume / internal_zone.area
usage = Usage() usage = Usage()
usage.name = usage_name 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 usage.percentage = 1
self._calculate_reduced_values_from_extended_library(usage, archetype_usage) self._calculate_reduced_values_from_extended_library(usage, archetype_usage)
@ -69,7 +71,7 @@ class ComnetUsageParameters:
raise KeyError('archetype not found') raise KeyError('archetype not found')
@staticmethod @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 # 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. # usage.occupancy when writing usage.occupancy = archetype.occupancy.
# Same happens for lighting and appliances. Therefore, this walk around has been done. # 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.heating_set_point_schedules = archetype.thermal_control.heating_set_point_schedules
_control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules _control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules
usage.thermal_control = _control 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 @staticmethod
def _calculate_reduced_values_from_extended_library(usage, archetype): 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 import sys
from hub.hub_logger import logger
import hub.helpers.constants as cte import hub.helpers.constants as cte
from hub.helpers.dictionaries import Dictionaries from hub.helpers.dictionaries import Dictionaries
from hub.city_model_structure.building_demand.usage import Usage 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.occupancy import Occupancy
from hub.city_model_structure.building_demand.appliances import Appliances 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.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 from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
@ -39,16 +41,16 @@ class NrcanUsageParameters:
try: try:
archetype_usage = self._search_archetypes(nrcan_catalog, usage_name) archetype_usage = self._search_archetypes(nrcan_catalog, usage_name)
except KeyError: except KeyError:
sys.stderr.write(f'Building {building.name} has unknown usage archetype for building function:' logger.error(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
f' {building.function}') sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
continue continue
usage_name = Dictionaries().hub_usage_to_comnet_usage[building.function] usage_name = Dictionaries().hub_usage_to_comnet_usage[building.function]
try: try:
comnet_archetype_usage = self._search_archetypes(comnet_catalog, usage_name) comnet_archetype_usage = self._search_archetypes(comnet_catalog, usage_name)
except KeyError: except KeyError:
sys.stderr.write(f'Building {building.name} has unknown usage archetype for building function:' logger.error(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
f' {building.function}') sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
continue continue
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
@ -61,7 +63,7 @@ class NrcanUsageParameters:
volume_per_area = internal_zone.volume / internal_zone.area volume_per_area = internal_zone.volume / internal_zone.area
usage = Usage() usage = Usage()
usage.name = usage_name 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) self._assign_comnet_extra_values(usage, comnet_archetype_usage)
usage.percentage = 1 usage.percentage = 1
self._calculate_reduced_values_from_extended_library(usage, archetype_usage) self._calculate_reduced_values_from_extended_library(usage, archetype_usage)
@ -77,7 +79,7 @@ class NrcanUsageParameters:
raise KeyError('archetype not found') raise KeyError('archetype not found')
@staticmethod @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: if archetype.mechanical_air_change > 0:
usage.mechanical_air_change = archetype.mechanical_air_change usage.mechanical_air_change = archetype.mechanical_air_change
elif archetype.ventilation_rate > 0: elif archetype.ventilation_rate > 0:
@ -111,6 +113,14 @@ class NrcanUsageParameters:
_control.heating_set_point_schedules = archetype.thermal_control.heating_set_point_schedules _control.heating_set_point_schedules = archetype.thermal_control.heating_set_point_schedules
_control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules _control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules
usage.thermal_control = _control 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 @staticmethod
def _assign_comnet_extra_values(usage, archetype): def _assign_comnet_extra_values(usage, archetype):

View File

@ -32,14 +32,13 @@ class EpwWeatherParameters:
_ = file.readline().split(',') _ = file.readline().split(',')
line = file.readline().split(',') line = file.readline().split(',')
number_records = int(line[1]) number_records = int(line[1])
depth_measurement_ground_temperature = [] ground_temperature = {}
ground_temperature = []
for i in range(0, number_records): 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 = [] temperatures = []
for j in range(0, 12): for j in range(0, 12):
temperatures.append(line[i*16+j+6]) temperatures.append(line[i*16+j+6])
ground_temperature.append(temperatures) ground_temperature[depth_measurement_ground_temperature] = temperatures
file.close() file.close()
except SystemExit: except SystemExit:
sys.stderr.write(f'Error: weather file {self._path} not found. Please download it from ' sys.stderr.write(f'Error: weather file {self._path} not found. Please download it from '
@ -74,6 +73,7 @@ class EpwWeatherParameters:
sys.exit() sys.exit()
for building in self._city.buildings: for building in self._city.buildings:
building.ground_temperature[cte.MONTH] = ground_temperature
if cte.HOUR in building.external_temperature: if cte.HOUR in building.external_temperature:
del building.external_temperature[cte.HOUR] del building.external_temperature[cte.HOUR]
new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw']) 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 building.beam[cte.HOUR] = new_value
else: else:
pd.concat([building.beam[cte.HOUR], new_value], axis=1) 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 # create the monthly and yearly values out of the hourly
for building in self._city.buildings: for building in self._city.buildings:
if cte.MONTH not in building.external_temperature: 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: 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 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 Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import math import math
import hub.helpers.constants as cte import hub.helpers.constants as cte
import pandas as pd import pandas as pd
@ -20,7 +21,7 @@ class Weather:
def sky_temperature(ambient_temperature): def sky_temperature(ambient_temperature):
""" """
Get sky temperature from ambient temperature in Celsius 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 # Swinbank - Source sky model approximation(1963) based on cloudiness statistics(32 %) in United States
# ambient temperatures( in °C) # ambient temperatures( in °C)
@ -32,6 +33,37 @@ class Weather:
values.append(value) values.append(value)
return values 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): def get_monthly_mean_values(self, values):
out = None out = None
if values is not None: if values is not None:
@ -41,7 +73,8 @@ class Weather:
del out['month'] del out['month']
return out return out
def get_yearly_mean_values(self, values): @staticmethod
def get_yearly_mean_values(values):
return values.mean() return values.mean()
def get_total_month(self, values): def get_total_month(self, values):

View File

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

View File

@ -124,3 +124,7 @@ class TestUsageFactory(TestCase):
self.assertIsNotNone(appliances.schedules, 'appliances schedule is none') self.assertIsNotNone(appliances.schedules, 'appliances schedule is none')
self.assertIsNotNone(usage.thermal_control.hvac_availability_schedules, self.assertIsNotNone(usage.thermal_control.hvac_availability_schedules,
'control hvac availability is none') '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')