meb_debugging #8
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
32
hub/catalog_factories/data_models/cost/chapter.py
Normal file
32
hub/catalog_factories/data_models/cost/chapter.py
Normal 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
|
48
hub/catalog_factories/data_models/cost/cost_helper.py
Normal file
48
hub/catalog_factories/data_models/cost/cost_helper.py
Normal 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
|
|
@ -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
|
|
54
hub/catalog_factories/data_models/cost/fuel.py
Normal file
54
hub/catalog_factories/data_models/cost/fuel.py
Normal 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
|
|
@ -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
|
|
|
@ -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
|
|
||||||
|
|
68
hub/catalog_factories/data_models/cost/item_description.py
Normal file
68
hub/catalog_factories/data_models/cost/item_description.py
Normal 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
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
189
hub/catalog_factories/energy_systems/nrcan_catalog.py
Normal file
189
hub/catalog_factories/energy_systems/nrcan_catalog.py
Normal 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")
|
42
hub/catalog_factories/energy_systems_catalog_factory.py
Normal file
42
hub/catalog_factories/energy_systems_catalog_factory.py
Normal 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)
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
|
@ -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:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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
|
|
@ -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>
|
11
hub/data/energy_systems/nrcan.xml
Normal file
11
hub/data/energy_systems/nrcan.xml
Normal 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>
|
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'],
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user