merge branch
This commit is contained in:
parent
301ea48953
commit
1b80543bb1
@ -1,25 +1,9 @@
|
||||
"""
|
||||
Cost workflow initialization
|
||||
"""
|
||||
import glob
|
||||
import os
|
||||
from pathlib import Path
|
||||
from .capital_costs import CapitalCosts
|
||||
from .end_of_life_costs import EndOfLifeCosts
|
||||
from .total_maintenance_costs import TotalMaintenanceCosts
|
||||
from .total_operational_costs import TotalOperationalCosts
|
||||
from .total_operational_incomes import TotalOperationalIncomes
|
||||
|
||||
|
||||
# constants
|
||||
CURRENT_STATUS = 0
|
||||
SKIN_RETROFIT = 1
|
||||
SYSTEM_RETROFIT_AND_PV = 2
|
||||
SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV = 3
|
||||
RETROFITTING_SCENARIOS = [
|
||||
CURRENT_STATUS,
|
||||
SKIN_RETROFIT,
|
||||
SYSTEM_RETROFIT_AND_PV,
|
||||
SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV
|
||||
]
|
||||
tmp_folder = Path('./tmp').resolve()
|
||||
out_path = Path('./outputs').resolve()
|
||||
files = glob.glob(f'{out_path}/*')
|
||||
for file in files:
|
||||
if file != '.gitignore':
|
||||
os.remove(file)
|
||||
|
@ -1,11 +1,7 @@
|
||||
"""
|
||||
Configuration module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Project Author Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
Code contributor Pilar Monsalvete Alvarez de Uribarri pilar_monsalvete@concordia.ca
|
||||
Code contributor Oriol Gavalda Torrellas oriol.gavalda@concordia.ca
|
||||
"""
|
||||
from hub.catalog_factories.costs_catalog_factory import CostCatalogFactory
|
||||
from hub.catalog_factories.costs_catalog_factory import CostsCatalogFactory
|
||||
from hub.catalog_factories.catalog import Catalog
|
||||
|
||||
|
||||
@ -25,7 +21,10 @@ class Configuration:
|
||||
gas_price_index,
|
||||
discount_rate,
|
||||
retrofitting_year_construction,
|
||||
factories_handler
|
||||
factories_handler,
|
||||
retrofit_scenario,
|
||||
fuel_type,
|
||||
dictionary
|
||||
):
|
||||
self._number_of_years = number_of_years
|
||||
self._percentage_credit = percentage_credit
|
||||
@ -38,7 +37,10 @@ class Configuration:
|
||||
self._discount_rate = discount_rate
|
||||
self._retrofitting_year_construction = retrofitting_year_construction
|
||||
self._factories_handler = factories_handler
|
||||
self._cost_catalog = CostCatalogFactory(factories_handler).catalog
|
||||
self._costs_catalog = CostsCatalogFactory(factories_handler).catalog
|
||||
self._retrofit_scenario = retrofit_scenario
|
||||
self._fuel_type = fuel_type
|
||||
self._dictionary = dictionary
|
||||
|
||||
@property
|
||||
def number_of_years(self):
|
||||
@ -195,8 +197,29 @@ class Configuration:
|
||||
self._factories_handler = value
|
||||
|
||||
@property
|
||||
def cost_catalog(self) -> Catalog:
|
||||
def costs_catalog(self) -> Catalog:
|
||||
"""
|
||||
Get cost catalog
|
||||
Get costs catalog
|
||||
"""
|
||||
return self._cost_catalog
|
||||
return self._costs_catalog
|
||||
|
||||
@property
|
||||
def retrofit_scenario(self):
|
||||
"""
|
||||
Get retrofit scenario
|
||||
"""
|
||||
return self._retrofit_scenario
|
||||
|
||||
@property
|
||||
def fuel_type(self):
|
||||
"""
|
||||
Get fuel type (0: Electricity, 1: Gas)
|
||||
"""
|
||||
return self._fuel_type
|
||||
|
||||
@property
|
||||
def dictionary(self):
|
||||
"""
|
||||
Get hub function to cost function dictionary
|
||||
"""
|
||||
return self._dictionary
|
217
costs/cost.py
217
costs/cost.py
@ -1,20 +1,14 @@
|
||||
"""
|
||||
Cost module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Project Author Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||
Code contributor Pilar Monsalvete Alvarez de Uribarri pilar_monsalvete@concordia.ca
|
||||
Code contributor Oriol Gavalda Torrellas oriol.gavalda@concordia.ca
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import numpy_financial as npf
|
||||
import hub.helpers.dictionaries
|
||||
import pandas as pd
|
||||
from hub.persistence.models.city_object import CityObject
|
||||
import numpy_financial as npf
|
||||
from hub.city_model_structure.building import Building
|
||||
|
||||
from configuration import Configuration
|
||||
from costs.results import Results
|
||||
from life_cycle_costs import LifeCycleCosts
|
||||
from costs.configuration import Configuration
|
||||
from costs import CapitalCosts, EndOfLifeCosts, TotalMaintenanceCosts, TotalOperationalCosts, TotalOperationalIncomes
|
||||
from costs.constants import CURRENT_STATUS
|
||||
|
||||
|
||||
class Cost:
|
||||
@ -23,8 +17,7 @@ class Cost:
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
buildings: [CityObject],
|
||||
buildings_results: dict,
|
||||
building: Building,
|
||||
number_of_years=31,
|
||||
percentage_credit=0,
|
||||
interest_rate=0.04,
|
||||
@ -35,9 +28,13 @@ class Cost:
|
||||
gas_price_index=0.05,
|
||||
discount_rate=0.03,
|
||||
retrofitting_year_construction=2020,
|
||||
factories_handler='montreal_custom'):
|
||||
self._buildings = buildings
|
||||
self._results = Results(buildings_results)
|
||||
factories_handler='montreal_custom',
|
||||
retrofit_scenario=CURRENT_STATUS,
|
||||
dictionary=hub.helpers.dictionaries.Dictionaries().hub_function_to_montreal_custom_costs_function):
|
||||
self._building = building
|
||||
fuel_type = 0
|
||||
if "gas" in building.energy_systems_archetype_name:
|
||||
fuel_type = 1
|
||||
self._configuration = Configuration(number_of_years,
|
||||
percentage_credit,
|
||||
interest_rate, credit_years,
|
||||
@ -47,21 +44,27 @@ class Cost:
|
||||
gas_price_index,
|
||||
discount_rate,
|
||||
retrofitting_year_construction,
|
||||
factories_handler)
|
||||
self._global_capital_costs = None
|
||||
self._global_capital_incomes = None
|
||||
self._global_end_of_life_costs = None
|
||||
self._global_operational_costs = None
|
||||
self._global_maintenance_costs = None
|
||||
self._global_operational_incomes = None
|
||||
factories_handler,
|
||||
retrofit_scenario,
|
||||
fuel_type,
|
||||
dictionary)
|
||||
|
||||
def _life_cycle_costs(self, building: CityObject, building_results: dict):
|
||||
lcc = LifeCycleCosts(building, building_results, self._configuration)
|
||||
self._global_capital_costs, self._global_capital_incomes = lcc.calculate_capital_costs
|
||||
self._global_end_of_life_costs = lcc.calculate_end_of_life_costs
|
||||
self._global_operational_costs = lcc.calculate_total_operational_costs
|
||||
self._global_maintenance_costs = lcc.calculate_total_maintenance_costs
|
||||
self._global_operational_incomes = lcc.calculate_total_operational_incomes
|
||||
@property
|
||||
def building(self) -> Building:
|
||||
"""
|
||||
Get current building.
|
||||
"""
|
||||
return self._building
|
||||
|
||||
@building.setter
|
||||
def building(self, value: Building):
|
||||
"""
|
||||
Set current building.
|
||||
"""
|
||||
self._building = value
|
||||
|
||||
def _npv_from_list(self, list_cashflow):
|
||||
return npf.npv(self._configuration.discount_rate, list_cashflow)
|
||||
|
||||
@property
|
||||
def life_cycle(self) -> pd.DataFrame:
|
||||
@ -70,93 +73,71 @@ class Cost:
|
||||
:return: DataFrame
|
||||
"""
|
||||
results = pd.DataFrame()
|
||||
for building_index, building in enumerate(self._buildings):
|
||||
self._life_cycle_costs(building, self._buildings_results[building_index])
|
||||
df_capital_costs_skin = (
|
||||
self._global_capital_costs['B2010_opaque_walls'] +
|
||||
self._global_capital_costs['B2020_transparent'] +
|
||||
self._global_capital_costs['B3010_opaque_roof'] +
|
||||
self._global_capital_costs['B10_superstructure']
|
||||
)
|
||||
df_capital_costs_systems = (
|
||||
self._global_capital_costs['D3020_heat_generating_systems'] +
|
||||
self._global_capital_costs['D3030_cooling_generation_systems'] +
|
||||
self._global_capital_costs['D3080_other_hvac_ahu'] +
|
||||
self._global_capital_costs['D5020_lighting_and_branch_wiring'] +
|
||||
self._global_capital_costs['D301010_photovoltaic_system']
|
||||
)
|
||||
df_end_of_life_costs = self._global_end_of_life_costs['End_of_life_costs']
|
||||
df_operational_costs = (
|
||||
self._global_operational_costs['Fixed_costs_electricity_peak'] +
|
||||
self._global_operational_costs['Fixed_costs_electricity_monthly'] +
|
||||
self._global_operational_costs['Fixed_costs_electricity_peak'] +
|
||||
self._global_operational_costs['Fixed_costs_electricity_monthly'] +
|
||||
self._global_operational_costs['Variable_costs_electricity'] +
|
||||
self._global_operational_costs['Fixed_costs_gas'] +
|
||||
self._global_operational_costs['Variable_costs_gas']
|
||||
)
|
||||
df_maintenance_costs = (
|
||||
self._global_maintenance_costs['Heating_maintenance'] +
|
||||
self._global_maintenance_costs['Cooling_maintenance'] +
|
||||
self._global_maintenance_costs['PV_maintenance']
|
||||
)
|
||||
df_operational_incomes = self._global_operational_incomes['Incomes electricity']
|
||||
df_capital_incomes = (
|
||||
self._global_capital_incomes['Subsidies construction'] +
|
||||
self._global_capital_incomes['Subsidies HVAC'] +
|
||||
self._global_capital_incomes['Subsidies PV']
|
||||
)
|
||||
life_cycle_costs_capital_skin = npf.npv(
|
||||
self._configuration.discount_rate, df_capital_costs_skin.values.tolist()
|
||||
)
|
||||
life_cycle_costs_capital_systems = npf.npv(
|
||||
self._configuration.discount_rate, df_capital_costs_systems.values.tolist()
|
||||
)
|
||||
life_cycle_costs_end_of_life_costs = npf.npv(
|
||||
self._configuration.discount_rate, df_end_of_life_costs.values.tolist()
|
||||
)
|
||||
life_cycle_operational_costs = npf.npv(
|
||||
self._configuration.discount_rate, df_operational_costs.values.tolist()
|
||||
)
|
||||
life_cycle_maintenance_costs = npf.npv(
|
||||
self._configuration.discount_rate, df_maintenance_costs.values.tolist()
|
||||
)
|
||||
life_cycle_operational_incomes = npf.npv(
|
||||
self._configuration.discount_rate, df_operational_incomes.values.tolist()
|
||||
)
|
||||
life_cycle_capital_incomes = npf.npv(
|
||||
self._configuration.discount_rate, df_capital_incomes.values.tolist()
|
||||
)
|
||||
global_capital_costs, global_capital_incomes = CapitalCosts(self._building, self._configuration).calculate()
|
||||
global_end_of_life_costs = EndOfLifeCosts(self._building, self._configuration).calculate()
|
||||
global_operational_costs = TotalOperationalCosts(self._building, self._configuration).calculate()
|
||||
global_maintenance_costs = TotalMaintenanceCosts(self._building, self._configuration).calculate()
|
||||
global_operational_incomes = TotalOperationalIncomes(self._building, self._configuration).calculate()
|
||||
|
||||
results[f'{building.name}_{building.city_id}'] = [life_cycle_costs_capital_skin,
|
||||
life_cycle_costs_capital_systems,
|
||||
life_cycle_costs_end_of_life_costs,
|
||||
life_cycle_operational_costs,
|
||||
life_cycle_maintenance_costs,
|
||||
life_cycle_operational_incomes,
|
||||
life_cycle_capital_incomes]
|
||||
df_capital_costs_skin = (
|
||||
global_capital_costs['B2010_opaque_walls'] +
|
||||
global_capital_costs['B2020_transparent'] +
|
||||
global_capital_costs['B3010_opaque_roof'] +
|
||||
global_capital_costs['B10_superstructure']
|
||||
)
|
||||
df_capital_costs_systems = (
|
||||
global_capital_costs['D3020_heat_generating_systems'] +
|
||||
global_capital_costs['D3030_cooling_generation_systems'] +
|
||||
global_capital_costs['D3080_other_hvac_ahu'] +
|
||||
global_capital_costs['D5020_lighting_and_branch_wiring'] +
|
||||
global_capital_costs['D301010_photovoltaic_system']
|
||||
)
|
||||
df_end_of_life_costs = global_end_of_life_costs['End_of_life_costs']
|
||||
df_operational_costs = (
|
||||
global_operational_costs['Fixed_costs_electricity_peak'] +
|
||||
global_operational_costs['Fixed_costs_electricity_monthly'] +
|
||||
global_operational_costs['Fixed_costs_electricity_peak'] +
|
||||
global_operational_costs['Fixed_costs_electricity_monthly'] +
|
||||
global_operational_costs['Variable_costs_electricity'] +
|
||||
global_operational_costs['Fixed_costs_gas'] +
|
||||
global_operational_costs['Variable_costs_gas']
|
||||
)
|
||||
df_maintenance_costs = (
|
||||
global_maintenance_costs['Heating_maintenance'] +
|
||||
global_maintenance_costs['Cooling_maintenance'] +
|
||||
global_maintenance_costs['PV_maintenance']
|
||||
)
|
||||
df_operational_incomes = global_operational_incomes['Incomes electricity']
|
||||
df_capital_incomes = (
|
||||
global_capital_incomes['Subsidies construction'] +
|
||||
global_capital_incomes['Subsidies HVAC'] +
|
||||
global_capital_incomes['Subsidies PV']
|
||||
)
|
||||
|
||||
life_cycle_costs_capital_skin = self._npv_from_list(df_capital_costs_skin.values.tolist())
|
||||
life_cycle_costs_capital_systems = self._npv_from_list(df_capital_costs_systems.values.tolist())
|
||||
life_cycle_costs_end_of_life_costs = self._npv_from_list(df_end_of_life_costs.values.tolist())
|
||||
life_cycle_operational_costs = self._npv_from_list(df_operational_costs.values.tolist())
|
||||
life_cycle_maintenance_costs = self._npv_from_list(df_maintenance_costs.values.tolist())
|
||||
life_cycle_operational_incomes = self._npv_from_list(df_operational_incomes.values.tolist())
|
||||
life_cycle_capital_incomes = self._npv_from_list(df_capital_incomes.values.tolist())
|
||||
|
||||
results[f'Scenario {self._configuration.retrofit_scenario}'] = [
|
||||
life_cycle_costs_capital_skin,
|
||||
life_cycle_costs_capital_systems,
|
||||
life_cycle_costs_end_of_life_costs,
|
||||
life_cycle_operational_costs,
|
||||
life_cycle_maintenance_costs,
|
||||
life_cycle_operational_incomes,
|
||||
life_cycle_capital_incomes
|
||||
]
|
||||
|
||||
results.index = ['total_capital_costs_skin',
|
||||
'total_capital_costs_systems',
|
||||
'end_of_life_costs',
|
||||
'total_operational_costs',
|
||||
'total_maintenance_costs',
|
||||
'operational_incomes',
|
||||
'capital_incomes']
|
||||
|
||||
results.index = ['total_capital_costs_skin',
|
||||
'total_capital_costs_systems',
|
||||
'end_of_life_costs',
|
||||
'total_operational_costs',
|
||||
'total_maintenance_costs',
|
||||
'operational_incomes',
|
||||
'capital_incomes']
|
||||
return results
|
||||
|
||||
def to_xlsx(self, path: Path):
|
||||
"""
|
||||
Export life cycle costs to xls file
|
||||
:return: none
|
||||
"""
|
||||
for building_index, building in enumerate(self._buildings):
|
||||
_path = (path / f'{building.name}_{building.city_id}').resolve()
|
||||
self._life_cycle_costs(building, self._buildings_results[building_index])
|
||||
with pd.ExcelWriter(path) as writer:
|
||||
self._global_capital_costs.to_excel(writer, sheet_name='global_capital_costs')
|
||||
self._global_end_of_life_costs.to_excel(writer, sheet_name='global_end_of_life_costs')
|
||||
self._global_operational_costs.to_excel(writer, sheet_name='global_operational_costs')
|
||||
self._global_maintenance_costs.to_excel(writer, sheet_name='global_maintenance_costs')
|
||||
self._global_operational_incomes.to_excel(writer, sheet_name='global_operational_incomes')
|
||||
self._global_capital_incomes.to_excel(writer, sheet_name='global_capital_incomes')
|
||||
|
@ -1,2 +0,0 @@
|
||||
numpy_financial
|
||||
cerc_hub
|
Loading…
Reference in New Issue
Block a user