From 64384876a4087556221dd814ae46fb70c1800e48 Mon Sep 17 00:00:00 2001 From: Pilar Date: Thu, 16 Mar 2023 10:06:32 -0400 Subject: [PATCH] updating costs catalog -> not completed --- .../cost/montreal_custom_catalog.py | 175 ++++++++++-------- .../data_models/cost/archetype.py | 36 +++- .../data_models/cost/capital_cost.py | 74 +++----- .../data_models/cost/chapter.py | 32 ++++ .../data_models/cost/cost_helper.py | 54 ++++++ .../data_models/cost/envelope.py | 66 ------- .../data_models/cost/fuel.py | 54 ++++++ .../data_models/cost/hvac.py | 96 ---------- .../data_models/cost/income.py | 74 ++++---- .../data_models/cost/item_description.py | 68 +++++++ .../data_models/cost/operational_cost.py | 102 +++------- .../data_models/cost/shell.py | 64 ------- .../data_models/cost/systems.py | 106 ----------- hub/data/costs/montreal_costs.xml | 100 +++++----- hub/helpers/constants.py | 22 +++ .../data/hft_function_to_hub_function.py | 30 +-- hub/helpers/dictionaries.py | 1 + hub/unittests/test_exports.py | 2 - 18 files changed, 504 insertions(+), 652 deletions(-) create mode 100644 hub/catalog_factories/data_models/cost/chapter.py create mode 100644 hub/catalog_factories/data_models/cost/cost_helper.py delete mode 100644 hub/catalog_factories/data_models/cost/envelope.py create mode 100644 hub/catalog_factories/data_models/cost/fuel.py delete mode 100644 hub/catalog_factories/data_models/cost/hvac.py create mode 100644 hub/catalog_factories/data_models/cost/item_description.py delete mode 100644 hub/catalog_factories/data_models/cost/shell.py delete mode 100644 hub/catalog_factories/data_models/cost/systems.py diff --git a/hub/catalog_factories/cost/montreal_custom_catalog.py b/hub/catalog_factories/cost/montreal_custom_catalog.py index e86fd3cd..a5a921ab 100644 --- a/hub/catalog_factories/cost/montreal_custom_catalog.py +++ b/hub/catalog_factories/cost/montreal_custom_catalog.py @@ -1,20 +1,21 @@ """ Cost catalog SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group +Copyright © 2023 Concordia CERC group Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ import xmltodict from hub.catalog_factories.catalog import Catalog -from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost -from hub.catalog_factories.data_models.cost.envelope import Envelope -from hub.catalog_factories.data_models.cost.systems import Systems -from hub.catalog_factories.data_models.cost.hvac import Hvac -from hub.catalog_factories.data_models.cost.operational_cost import OperationalCost -from hub.catalog_factories.data_models.cost.income import Income from hub.catalog_factories.data_models.cost.archetype import Archetype from hub.catalog_factories.data_models.cost.content import Content +from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost +from hub.catalog_factories.data_models.cost.chapter import Chapter +from hub.catalog_factories.data_models.cost.item_description import ItemDescription +from hub.catalog_factories.data_models.cost.operational_cost import OperationalCost +from hub.catalog_factories.data_models.cost.fuel import Fuel +from hub.catalog_factories.data_models.cost.income import Income +from hub.catalog_factories.data_models.cost.cost_helper import CostHelper class MontrealCustomCatalog(Catalog): @@ -27,90 +28,93 @@ class MontrealCustomCatalog(Catalog): self._content = Content(self._load_archetypes()) @staticmethod - def _get_threesome(entry): - _reposition = float(entry['reposition']['#text']) - _investment = float(entry['initial_investment']['#text']) - _lifetime = float(entry['lifetime_equipment']['#text']) - return _reposition, _investment, _lifetime + def _item_with_threesome(entry, item_type): + _reposition = float(entry[item_type]['reposition']['#text']) + _reposition_unit = entry[item_type]['reposition']['@cost_unit'] + _investment = float(entry[item_type]['investment_cost']['#text']) + _investment_unit = entry[item_type]['investment_cost']['@cost_unit'] + _lifetime = float(entry[item_type]['lifetime_equipment']['#text']) + _item_description = ItemDescription(item_type, + initial_investment=_investment, + initial_investment_units=_investment_unit, + reposition=_reposition, + reposition_units=_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_units=_refurbishment_unit) + return _item_description def _get_capital_costs(self, entry): - structural = float(entry['structural']['#text']) - sub_structural = float(entry['sub_structural']['#text']) - surface_finish = float(entry['surface_finish']['#text']) - engineer = float(entry['engineer']['#text']) - opaque_reposition, opaque_initial_investment, opaque_lifetime = \ - self._get_threesome(entry['envelope']['opaque']) - transparent_reposition, transparent_initial_investment, transparent_lifetime = \ - self._get_threesome(entry['envelope']['transparent']) - envelope = Envelope(opaque_reposition, - opaque_initial_investment, - opaque_lifetime, - transparent_reposition, - transparent_initial_investment, - transparent_lifetime) - heating_equipment_reposition, heating_equipment_initial_investment, heating_equipment_lifetime = \ - self._get_threesome(entry['systems']['hvac']['heating_equipment_cost']) - heating_equipment_reposition = heating_equipment_reposition / 1000 - heating_equipment_initial_investment = heating_equipment_initial_investment / 1000 - cooling_equipment_reposition, cooling_equipment_initial_investment, cooling_equipment_lifetime = \ - self._get_threesome(entry['systems']['hvac']['cooling_equipment_cost']) - cooling_equipment_reposition = cooling_equipment_reposition / 1000 - cooling_equipment_initial_investment = cooling_equipment_initial_investment / 1000 - general_hvac_equipment_reposition, general_hvac_equipment_initial_investment, general_hvac_equipment_lifetime = \ - self._get_threesome(entry['systems']['hvac']['general_hvac_equipment_cost']) - general_hvac_equipment_reposition = general_hvac_equipment_reposition * 3600 - general_hvac_equipment_initial_investment = general_hvac_equipment_initial_investment * 3600 - hvac = Hvac(heating_equipment_reposition, heating_equipment_initial_investment, heating_equipment_lifetime, - cooling_equipment_reposition, cooling_equipment_initial_investment, cooling_equipment_lifetime, - general_hvac_equipment_reposition, general_hvac_equipment_initial_investment, - general_hvac_equipment_lifetime) + general_chapters = [] + chapters_titles = CostHelper().chapters_in_lod1 + items_list = [] + item_type = 'B10_superstructure' + item_description = self._item_with_refurbishment_values(entry, item_type) + items_list.append(item_description) + for item in entry['B20_envelope']: + item_type = item + item_description = self._item_with_refurbishment_values(entry['B20_envelope'], item_type) + items_list.append(item_description) + item_type = 'B30_roofing' + item_description = self._item_with_refurbishment_values(entry, item_type) + items_list.append(item_description) + general_chapters.append(Chapter('B_shell', items_list)) - photovoltaic_system_reposition, photovoltaic_system_initial_investment, photovoltaic_system_lifetime = \ - self._get_threesome(entry['systems']['photovoltaic_system']) - other_conditioning_systems_reposition, other_conditioning_systems_initial_investment, \ - other_conditioning_systems_lifetime = self._get_threesome(entry['systems']['other_systems']) - lighting_reposition, lighting_initial_investment, lighting_lifetime = \ - self._get_threesome(entry['systems']['lighting']) - systems = Systems(hvac, - photovoltaic_system_reposition, - photovoltaic_system_initial_investment, - photovoltaic_system_lifetime, - other_conditioning_systems_reposition, - other_conditioning_systems_initial_investment, - other_conditioning_systems_lifetime, - lighting_reposition, - lighting_initial_investment, - lighting_lifetime) - _capital_cost = CapitalCost(structural, - sub_structural, - envelope, - systems, - surface_finish, - engineer) + items_list = [] + item_type = 'D301010_photovoltaic_system' + item_description = self._item_with_threesome(entry['D30_hvac']['D3010_energy_supply'], item_type) + items_list.append(item_description) + item_type_list = ['D3020_heat_generating_systems', 'D3030_cooling_generation_systems', 'D3040_distribution_systems', + 'D3080_other_hvac_ahu'] + for item_type in item_type_list: + item_description = self._item_with_threesome(entry['D30_hvac'], item_type) + items_list.append(item_description) + item_type = 'D5020lighting_and_branch_wiring' + item_description = self._item_with_threesome(entry['D50_electrical'], item_type) + items_list.append(item_description) + general_chapters.append(Chapter('D_services', items_list)) + + design_allowance = float(entry['Z_allowances_overhead_profit']['Z10_design_allowance']['#text']) + overhead_and_profit = float(entry['Z_allowances_overhead_profit']['Z10_overhead_and_profit']['#text']) + _capital_cost = CapitalCost(general_chapters, design_allowance, overhead_and_profit) return _capital_cost @staticmethod def _get_operational_costs(entry): - fuel_type = entry['fuel']['@fuel_type'] - fuel_fixed_operational_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text']) - fuel_fixed_operational_peak = float(entry['fuel']['fixed']['fixed_power']['#text']) / 1000 - fuel_variable_operational = float(entry['fuel']['variable']['#text']) / 1000 / 3600 + fuels = [] + for item in entry['fuels']: + fuel_type = item['fuel']['@fuel_type'] + fuel_variable = float(entry['fuel']['variable']['#text']) + fuel_variable_units = float(entry['fuel']['variable']['@cost_unit']) + fuel_fixed_monthly = None + fuel_fixed_peak = None + if fuel_type == 'electricity': + fuel_fixed_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text']) + fuel_fixed_peak = float(entry['fuel']['fixed']['fixed_power']['#text']) / 1000 + elif fuel_type == 'gas': + fuel_fixed_monthly = float(entry['fuel']['fixed']['fixed_monthly']['#text']) + fuel = Fuel(fuel_type, + fixed_monthly=fuel_fixed_monthly, + fixed_power=fuel_fixed_peak, + variable=fuel_variable, + variable_units=fuel_variable_units) + fuels.append(fuel) heating_equipment_maintenance = float(entry['maintenance']['heating_equipment']['#text']) / 1000 cooling_equipment_maintenance = float(entry['maintenance']['cooling_equipment']['#text']) / 1000 - general_hvac_equipment_maintenance = float(entry['maintenance']['general_hvac_equipment']['#text']) * 3600 photovoltaic_system_maintenance = float(entry['maintenance']['photovoltaic_system']['#text']) - other_systems_maintenance = float(entry['maintenance']['other_systems']['#text']) co2_emissions = float(entry['CO2_cost']['#text']) - _operational_cost = OperationalCost(fuel_type, - fuel_fixed_operational_monthly, - fuel_fixed_operational_peak, - fuel_variable_operational, + _operational_cost = OperationalCost(fuels, heating_equipment_maintenance, cooling_equipment_maintenance, - general_hvac_equipment_maintenance, photovoltaic_system_maintenance, - other_systems_maintenance, co2_emissions) return _operational_cost @@ -120,7 +124,10 @@ class MontrealCustomCatalog(Catalog): for archetype in archetypes: function = archetype['@function'] municipality = archetype['@municipality'] - currency = archetype['@currency'] + country = archetype['@country'] + lod = float(archetype['@lod']) + currency = archetype['currency'] + print(currency) capital_cost = self._get_capital_costs(archetype['capital_cost']) operational_cost = self._get_operational_costs(archetype['operational_cost']) end_of_life_cost = float(archetype['end_of_life_cost']['#text']) @@ -128,17 +135,21 @@ class MontrealCustomCatalog(Catalog): hvac = float(archetype['incomes']['subsidies']['hvac_subsidy']['#text']) photovoltaic_system = float(archetype['incomes']['subsidies']['photovoltaic_subsidy']['#text']) electricity_exports = float(archetype['incomes']['energy_exports']['electricity']['#text']) / 1000 / 3600 - heat_exports = float(archetype['incomes']['energy_exports']['heat']['#text']) / 1000 / 3600 - co2 = float(archetype['incomes']['CO2_income']['#text']) - income = Income(construction, hvac, photovoltaic_system, electricity_exports, heat_exports, co2) - _catalog_archetypes.append(Archetype(function, + reduction_tax = float(archetype['incomes']['tax_reduction']['#text']) + income = Income(construction_subsidy=construction, + hvac_subsidy=hvac, + photovoltaic_subsidy=photovoltaic_system, + electricity_export=electricity_exports, + reductions_taxes=reduction_tax) + _catalog_archetypes.append(Archetype(lod, + function, municipality, + country, currency, capital_cost, operational_cost, end_of_life_cost, income)) - return _catalog_archetypes def names(self, category=None): diff --git a/hub/catalog_factories/data_models/cost/archetype.py b/hub/catalog_factories/data_models/cost/archetype.py index 69ba2654..cf24c6ee 100644 --- a/hub/catalog_factories/data_models/cost/archetype.py +++ b/hub/catalog_factories/data_models/cost/archetype.py @@ -1,8 +1,8 @@ """ Archetype catalog Cost SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Atiya atiya.atiya@mail.concordia.ca +Copyright © 2023 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost @@ -11,9 +11,21 @@ from hub.catalog_factories.data_models.cost.income import Income class Archetype: - def __init__(self, function, municipality, currency, capital_cost, operational_cost, end_of_life_cost, income): + def __init__(self, + lod, + function, + municipality, + country, + currency, + capital_cost, + operational_cost, + end_of_life_cost, + income): + + self._lod = lod self._function = function self._municipality = municipality + self._country = country self._currency = currency self._capital_cost = capital_cost self._operational_cost = operational_cost @@ -26,7 +38,15 @@ class Archetype: Get name :return: string """ - return f'{self._municipality}_{self._function}' + return f'{self._country}_{self._municipality}_{self._function}_{self._lod}' + + @property + def lod(self): + """ + Get level of detail of the catalog + :return: string + """ + return self._lod @property def function(self): @@ -44,6 +64,14 @@ class Archetype: """ return self._municipality + @property + def country(self): + """ + Get country + :return: string + """ + return self._country + @property def currency(self): """ diff --git a/hub/catalog_factories/data_models/cost/capital_cost.py b/hub/catalog_factories/data_models/cost/capital_cost.py index 6d5f2504..233043ac 100644 --- a/hub/catalog_factories/data_models/cost/capital_cost.py +++ b/hub/catalog_factories/data_models/cost/capital_cost.py @@ -1,68 +1,40 @@ """ -Cost catalog CapitalCost +Capital costs included in the catalog SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Atiya atiya.atiya@mail.concordia.ca -Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +Copyright © 2023 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ -from hub.catalog_factories.data_models.cost.envelope import Envelope -from hub.catalog_factories.data_models.cost.systems import Systems +from typing import List +from hub.catalog_factories.data_models.cost.chapter import Chapter class CapitalCost: - def __init__(self, structural, sub_structural, envelope, systems, surface_finish, engineer): - self._structural = structural - self._sub_structural = sub_structural - self._envelope = envelope - self._systems = systems - self._surface_finish = surface_finish - self._engineer = engineer + def __init__(self, general_chapters, design_allowance, overhead_and_profit): + self._general_chapters = general_chapters + self._design_allowance = design_allowance + self._overhead_and_profit = overhead_and_profit @property - def structural(self): + def general_chapters(self) -> List[Chapter]: """ - Get structural cost per building volume in currency/m3 + Get general chapters in capital costs + :return: [Chapter] + """ + return self._general_chapters + + @property + def design_allowance(self): + """ + Get design allowance in percentage :return: float """ - return self._structural + return self._design_allowance @property - def sub_structural(self): + def overhead_and_profit(self): """ - Get sub structural cost per building foot-print in currency/m2 + Get overhead profit in percentage :return: float """ - return self._sub_structural - - @property - def envelope(self) -> Envelope: - """ - Get envelope cost - :return: Envelope - """ - return self._envelope - - @property - def systems(self) -> Systems: - """ - Get systems cost - :return: Systems - """ - return self._systems - - @property - def surface_finish(self): - """ - Get surface finish cost per external surfaces areas in currency/m2 - :return: float - """ - return self._surface_finish - - @property - def engineer(self): - """ - Get engineer cost in % - :return: float - """ - return self._engineer + return self._overhead_and_profit diff --git a/hub/catalog_factories/data_models/cost/chapter.py b/hub/catalog_factories/data_models/cost/chapter.py new file mode 100644 index 00000000..d1be68ac --- /dev/null +++ b/hub/catalog_factories/data_models/cost/chapter.py @@ -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_list): + + self._chapter_type = chapter_type + self._items_list = items_list + + @property + def chapter_type(self): + """ + Get chapter type + :return: str + """ + return self._chapter_type + + @property + def items_list(self) -> List[ItemDescription]: + """ + Get list of items contained in the chapter + :return: [str] + """ + return self._items_list diff --git a/hub/catalog_factories/data_models/cost/cost_helper.py b/hub/catalog_factories/data_models/cost/cost_helper.py new file mode 100644 index 00000000..c51ab02b --- /dev/null +++ b/hub/catalog_factories/data_models/cost/cost_helper.py @@ -0,0 +1,54 @@ +""" +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 = { + 'B10_superstructure': cte.SUPERSTRUCTURE, + 'B20_envelope': cte.ENVELOPE, + 'B30_roofing': cte.ROOFING, + 'D3010_energy_supply': cte.ENERGY_SUPPLY, + 'D3020_heat_generating_systems': cte.HEAT_GENERATION, + 'D3030_cooling_generation_systems': cte.COOL_GENERATION, + 'D3040_distribution_systems': cte.DISTRIBUTION, + 'D3080_other_hvac_ahu': cte.OTHER_SYSTEMS, + 'D5020lighting_and_branch_wiring': cte.LIGHTING_AND_WIRING + } + + @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 diff --git a/hub/catalog_factories/data_models/cost/envelope.py b/hub/catalog_factories/data_models/cost/envelope.py deleted file mode 100644 index c2d2d419..00000000 --- a/hub/catalog_factories/data_models/cost/envelope.py +++ /dev/null @@ -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 diff --git a/hub/catalog_factories/data_models/cost/fuel.py b/hub/catalog_factories/data_models/cost/fuel.py new file mode 100644 index 00000000..974b3db2 --- /dev/null +++ b/hub/catalog_factories/data_models/cost/fuel.py @@ -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[(None, None), (float, str)]: + """ + Get variable costs in given units + :return: None, None or float, str + """ + return self._variable, self._variable_units diff --git a/hub/catalog_factories/data_models/cost/hvac.py b/hub/catalog_factories/data_models/cost/hvac.py deleted file mode 100644 index 01b6c7b7..00000000 --- a/hub/catalog_factories/data_models/cost/hvac.py +++ /dev/null @@ -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 diff --git a/hub/catalog_factories/data_models/cost/income.py b/hub/catalog_factories/data_models/cost/income.py index 9bc975f2..abd74f77 100644 --- a/hub/catalog_factories/data_models/cost/income.py +++ b/hub/catalog_factories/data_models/cost/income.py @@ -1,64 +1,62 @@ """ -Income from costs catalog +Incomes included in the costs catalog SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca +Copyright © 2023 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ +from typing import Union + class Income: - def __init__(self, construction, hvac, photovoltaic_system, electricity_exports, heat_exports, co2): - self._construction = construction - self._hvac = hvac - self._photovoltaic_system = photovoltaic_system - self._electricity_exports = electricity_exports - self._heat_exports = heat_exports - self._co2 = co2 + def __init__(self, construction_subsidy=None, + hvac_subsidy=None, + photovoltaic_subsidy=None, + electricity_export=None, + reductions_taxes=None): + + self._construction_subsidy = construction_subsidy + self._hvac_subsidy = hvac_subsidy + self._photovoltaic_subsidy = photovoltaic_subsidy + self._electricity_export = electricity_export + self._reductions_taxes = reductions_taxes @property - def construction(self): + def construction_subsidy(self) -> Union[None, float]: """ - Get construction subsidy in % of total investment construction cost - :return: float + Get subsidy for construction in percentage + :return: None or float """ - return self._construction + return self._construction_subsidy @property - def hvac(self): + def hvac_subsidy(self) -> Union[None, float]: """ - Get hvac subsidy in % of total investment HVAC cost - :return: float + Get subsidy for HVAC system in percentage + :return: None or float """ - return self._hvac + return self._hvac_subsidy @property - def photovoltaic_system(self): + def photovoltaic_subsidy(self) -> Union[None, float]: """ - Get photovoltaic system subsidy in % of total investment photovoltaic cost - :return: float + Get subsidy PV systems in percentage + :return: None or float """ - return self._photovoltaic_system + return self._photovoltaic_subsidy @property - def electricity_exports(self): + def electricity_export(self) -> Union[None, float]: """ - Get electricity exports gains in currency/J - :return: float + Get electricity export incomes in currency per J + :return: None or float """ - return self._construction + return self._construction_subsidy @property - def heat_exports(self): + def reductions_taxes(self) -> Union[None, float]: """ - Get heat exports gains in currency/J - :return: float + Get reduction in taxes in percentage + :return: None or float """ - return self._heat_exports - - @property - def co2(self): - """ - Get co2 income in currency/kg - :return: float - """ - return self._co2 + return self._reductions_taxes diff --git a/hub/catalog_factories/data_models/cost/item_description.py b/hub/catalog_factories/data_models/cost/item_description.py new file mode 100644 index 00000000..345e04b7 --- /dev/null +++ b/hub/catalog_factories/data_models/cost/item_description.py @@ -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_units=None, + refurbishment=None, + refurbishment_units=None, + reposition=None, + reposition_units=None, + lifetime=None): + + self._item_type = item_type + self._initial_investment = initial_investment + self._initial_investment_units = initial_investment_units + self._refurbishment = refurbishment + self._refurbishment_units = refurbishment_units + self._reposition = reposition + self._reposition_units = reposition_units + self._lifetime = lifetime + + @property + def type(self): + """ + Get item type + :return: str + """ + return self._item_type + + @property + def initial_investment(self) -> Union[(None, None), (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_units + + @property + def refurbishment(self) -> Union[(None, None), (float, str)]: + """ + Get refurbishment costs of the specific item in given units + :return: None, None or float, str + """ + return self._refurbishment, self._refurbishment_units + + @property + def reposition(self) -> Union[(None, None), (float, str)]: + """ + Get reposition costs of the specific item in given units + :return: None, None or float, str + """ + return self._reposition, self._reposition_units + + @property + def lifetime(self) -> Union[None, float]: + """ + Get lifetime in years + :return: None or float + """ + return self._lifetime diff --git a/hub/catalog_factories/data_models/cost/operational_cost.py b/hub/catalog_factories/data_models/cost/operational_cost.py index b1a7b3aa..f7cbcc6f 100644 --- a/hub/catalog_factories/data_models/cost/operational_cost.py +++ b/hub/catalog_factories/data_models/cost/operational_cost.py @@ -1,104 +1,58 @@ """ -Cost catalog OperationalCost +Operational costs included in the catalog SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Atiya atiya.atiya@mail.concordia.ca -Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +Copyright © 2023 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca """ +from typing import List +from hub.catalog_factories.data_models.cost.fuel import Fuel + class OperationalCost: - def __init__(self, fuel_type, fuel_fixed_operational_monthly, fuel_fixed_operational_peak, - fuel_variable_operational, heating_equipment_maintenance, cooling_equipment_maintenance, - general_hvac_equipment_maintenance, photovoltaic_system_maintenance, other_systems_maintenance, - co2_emissions): - self._fuel_type = fuel_type - self._fuel_fixed_operational_monthly = fuel_fixed_operational_monthly - self._fuel_fixed_operational_peak = fuel_fixed_operational_peak - self._fuel_variable_operational = fuel_variable_operational - self._heating_equipment_maintenance = heating_equipment_maintenance - self._cooling_equipment_maintenance = cooling_equipment_maintenance - self._general_hvac_equipment_maintenance = general_hvac_equipment_maintenance - self._photovoltaic_system_maintenance = photovoltaic_system_maintenance - self._other_systems_maintenance = other_systems_maintenance - self._co2_emissions = co2_emissions + def __init__(self, fuels, maintenance_heating, maintenance_cooling, maintenance_pv, co2): + self._fuels = fuels + self._maintenance_heating = maintenance_heating + self._maintenance_cooling = maintenance_cooling + self._maintenance_pv = maintenance_pv + self._co2 = co2 @property - def fuel_type(self): + def fuels(self) -> List[Fuel]: """ - Get fuel type - :return: string + Get fuels listed in capital costs + :return: [FUEL] """ - return self._fuel_type + return self._fuels @property - def fuel_fixed_operational_monthly(self): + def maintenance_heating(self): """ - Get fuel fixed operational cost in currency/month + Get cost of maintaining the heating system in currency/W :return: float """ - return self._fuel_fixed_operational_monthly + return self._maintenance_heating @property - def fuel_fixed_operational_peak(self): + def maintenance_cooling(self): """ - Get fuel fixed operational cost per peak power in currency/W + Get cost of maintaining the cooling system in currency/W :return: float """ - return self._fuel_fixed_operational_peak + return self._maintenance_cooling @property - def fuel_variable_operational(self): + def maintenance_pv(self): """ - Get fuel variable operational cost in currency/J + Get cost of maintaining the PV system in currency/m2 :return: float """ - return self._fuel_variable_operational + return self._maintenance_pv @property - def heating_equipment_maintenance(self): + def co2(self): """ - Get heating equipment maintenance cost per peak power in currency/W + Get cost of CO2 emissions in currency/kgCO2 :return: float """ - return self._heating_equipment_maintenance - - @property - def cooling_equipment_maintenance(self): - """ - Get cooling equipment maintenance cost per peak power in currency/W - :return: float - """ - return self._cooling_equipment_maintenance - - @property - def general_hvac_equipment_maintenance(self): - """ - Get general hvac equipment maintenance cost per peak-air-flow in currency/(m3/s) - :return: float - """ - return self._general_hvac_equipment_maintenance - - @property - def photovoltaic_system_maintenance(self): - """ - Get photovoltaic system maintenance cost per panels area in currency/m2 - :return: float - """ - return self._photovoltaic_system_maintenance - - @property - def other_systems_maintenance(self): - """ - Get other systems' maintenance cost per building's foot-print area in currency/m2 - :return: float - """ - return self._other_systems_maintenance - - @property - def co2_emissions(self): - """ - Get CO2 emissions cost in currency/kg - :return: float - """ - return self._co2_emissions + return self._co2 diff --git a/hub/catalog_factories/data_models/cost/shell.py b/hub/catalog_factories/data_models/cost/shell.py deleted file mode 100644 index d0465fd2..00000000 --- a/hub/catalog_factories/data_models/cost/shell.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -Shell costs from Cost catalog -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2023 Concordia CERC group -Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - - -class Shell: - def __init__(self, refurbishment_basement, envelope, roofing): - 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 diff --git a/hub/catalog_factories/data_models/cost/systems.py b/hub/catalog_factories/data_models/cost/systems.py deleted file mode 100644 index 7f2dc34e..00000000 --- a/hub/catalog_factories/data_models/cost/systems.py +++ /dev/null @@ -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 diff --git a/hub/data/costs/montreal_costs.xml b/hub/data/costs/montreal_costs.xml index 5853cbf1..1b40f6b8 100644 --- a/hub/data/costs/montreal_costs.xml +++ b/hub/data/costs/montreal_costs.xml @@ -1,5 +1,6 @@ - + + CAD @@ -63,48 +64,45 @@ - - + + 12.27 - 0 - - 0.075 - - - + 0 + 0.075 + + 17.71 - - 0.640 - - - 1.2 - - - 0.09 - - - 40 - 40 - 1 - + 0.640 + + + 1.2 + + + 0.09 + + + + 40 + 40 + 1 + 30 6.3 - - 2 - 1.5 - 3.6 - + + 2 + 1.5 + 3.6 + - 0 + 0 - - 2 - + 2 - + + CAD @@ -169,16 +167,12 @@ - - 12.27 - 0 - + 12.27 + 0 0.075 - - 17.71 - + 17.71 0.640 @@ -187,26 +181,24 @@ 0.09 - - 40 - 40 - 1 - + + 40 + 40 + 1 + 30 6.3 - - 2 - 1.5 - 3.6 - + + 2 + 1.5 + 3.6 + - 0 + 0 - - 2 - + 2 \ No newline at end of file diff --git a/hub/helpers/constants.py b/hub/helpers/constants.py index 8c601f5c..b67bd61a 100644 --- a/hub/helpers/constants.py +++ b/hub/helpers/constants.py @@ -158,3 +158,25 @@ MIN_FLOAT = float('-inf') # Tools SRA = 'sra' INSEL_MEB = 'insel meb' + +# Costs units +CURRENCY_PER_SQM = 'currency/m2' +CURRENCY_PER_CBM = 'currency/m3' +CURRENCY_PER_KW = 'currency/kW' +CURRENCY_PER_KWH = 'currency/kWh' +CURRENCY_PER_MONTH = 'currency/month' +CURRENCY_PER_LITRE = 'currency/l' +CURRENCY_PER_KG = 'currency/kg' +CURRENCY_PER_CBM_PER_HOUR = 'currency/(m3/h)' +PERCENTAGE = '%' + +# Costs chapters +SUPERSTRUCTURE = 'B10_superstructure' +ENVELOPE = 'B20_envelope' +ROOFING = 'B30_roofing' +ENERGY_SUPPLY = 'D3010_energy_supply' +HEAT_GENERATION = 'D3020_heat_generating_systems' +COOL_GENERATION = 'D3030_cooling_generation_systems' +DISTRIBUTION = 'D3040_distribution_systems' +OTHER_SYSTEMS = 'D3080_other_hvac_ahu' +LIGHTING_AND_WIRING = 'D5020lighting_and_branch_wiring' diff --git a/hub/helpers/data/hft_function_to_hub_function.py b/hub/helpers/data/hft_function_to_hub_function.py index 00f63a53..a14ddfb1 100644 --- a/hub/helpers/data/hft_function_to_hub_function.py +++ b/hub/helpers/data/hft_function_to_hub_function.py @@ -12,21 +12,21 @@ class HftFunctionToHubFunction: def __init__(self): self._dictionary = { - 'residential': cte.RESIDENTIAL, - 'single family house': cte.SINGLE_FAMILY_HOUSE, - 'multifamily house': cte.MULTI_FAMILY_HOUSE, - 'hotel': cte.HOTEL, - 'hospital': cte.HOSPITAL, - 'outpatient': cte.OUT_PATIENT_HEALTH_CARE, - 'commercial': cte.SUPERMARKET, - 'strip mall': cte.STRIP_MALL, - 'warehouse': cte.WAREHOUSE, - 'primary school': cte.PRIMARY_SCHOOL, - 'secondary school': cte.EDUCATION, - 'office': cte.MEDIUM_OFFICE, - 'large office': cte.LARGE_OFFICE - } + 'residential': cte.RESIDENTIAL, + 'single family house': cte.SINGLE_FAMILY_HOUSE, + 'multifamily house': cte.MULTI_FAMILY_HOUSE, + 'hotel': cte.HOTEL, + 'hospital': cte.HOSPITAL, + 'outpatient': cte.OUT_PATIENT_HEALTH_CARE, + 'commercial': cte.SUPERMARKET, + 'strip mall': cte.STRIP_MALL, + 'warehouse': cte.WAREHOUSE, + 'primary school': cte.PRIMARY_SCHOOL, + 'secondary school': cte.EDUCATION, + 'office': cte.MEDIUM_OFFICE, + 'large office': cte.LARGE_OFFICE + } @property - def dictionary(self) -> dict: + def dictionary(self) -> dict: return self._dictionary diff --git a/hub/helpers/dictionaries.py b/hub/helpers/dictionaries.py index 3561d682..1fc73fde 100644 --- a/hub/helpers/dictionaries.py +++ b/hub/helpers/dictionaries.py @@ -15,6 +15,7 @@ from hub.helpers.data.hub_usage_to_comnet_usage import HubUsageToComnetUsage from hub.helpers.data.hub_usage_to_hft_usage import HubUsageToHftUsage from hub.helpers.data.hub_usage_to_nrcan_usage import HubUsageToNrcanUsage + class Dictionaries: """ Dictionaries class diff --git a/hub/unittests/test_exports.py b/hub/unittests/test_exports.py index 283c9595..7fa84103 100644 --- a/hub/unittests/test_exports.py +++ b/hub/unittests/test_exports.py @@ -71,8 +71,6 @@ class TestExports(TestCase): self._complete_city = self._get_complete_city(from_pickle) EnergyBuildingsExportsFactory(export_type, self._complete_city, self._output_path).export() - - def test_obj_export(self): """ export to obj