diff --git a/costs/__init__.py b/costs/__init__.py index a0c42e0..0cf987a 100644 --- a/costs/__init__.py +++ b/costs/__init__.py @@ -5,18 +5,13 @@ import glob import os from pathlib import Path -CLIMATE_REFERENCE_CITY = 'Montreal' -WEATHER_FILE = 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw' -WEATHER_FORMAT = 'epw' +# configurable parameters +file_path = Path('./data/selected_building_2864.geojson').resolve() CONSTRUCTION_FORMAT = 'nrcan' USAGE_FORMAT = 'comnet' ENERGY_SYSTEM_FORMAT = 'montreal_custom' ATTIC_HEATED_CASE = 0 BASEMENT_HEATED_CASE = 1 -CURRENT_STATUS = 0 -SKIN_RETROFIT = 1 -SYSTEM_RETROFIT_AND_PV = 2 -SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV = 3 NUMBER_OF_YEARS = 31 CONSUMER_PRICE_INDEX = 0.04 ELECTRICITY_PEAK_INDEX = 0.05 @@ -24,13 +19,20 @@ ELECTRICITY_PRICE_INDEX = 0.05 GAS_PRICE_INDEX = 0.05 DISCOUNT_RATE = 0.03 RETROFITTING_YEAR_CONSTRUCTION = 2020 + +CLIMATE_REFERENCE_CITY = 'Montreal' +WEATHER_FILE = 'CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw' +WEATHER_FORMAT = 'epw' +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 ] -file_path = Path('./data/selected_building_2864.geojson').resolve() tmp_folder = Path('./tmp').resolve() out_path = Path('./outputs').resolve() files = glob.glob(f'{out_path}/*') diff --git a/costs/__main__.py b/costs/__main__.py index 2389ebe..e76efab 100644 --- a/costs/__main__.py +++ b/costs/__main__.py @@ -23,10 +23,11 @@ from sra_engine import SraEngine from life_cycle_costs import LifeCycleCosts # import constants -from costs import CLIMATE_REFERENCE_CITY, WEATHER_FILE, WEATHER_FORMAT, CONSTRUCTION_FORMAT, USAGE_FORMAT, RETROFITTING_YEAR_CONSTRUCTION +from costs import CLIMATE_REFERENCE_CITY, WEATHER_FILE, WEATHER_FORMAT, CONSTRUCTION_FORMAT, USAGE_FORMAT from costs import ENERGY_SYSTEM_FORMAT, ATTIC_HEATED_CASE, BASEMENT_HEATED_CASE, RETROFITTING_SCENARIOS, NUMBER_OF_YEARS from costs import CONSUMER_PRICE_INDEX, ELECTRICITY_PEAK_INDEX, ELECTRICITY_PRICE_INDEX, GAS_PRICE_INDEX, DISCOUNT_RATE from costs import SKIN_RETROFIT, SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV +from costs import RETROFITTING_YEAR_CONSTRUCTION # import paths from costs import file_path, tmp_folder, out_path @@ -111,7 +112,7 @@ for retrofitting_scenario in RETROFITTING_SCENARIOS: ELECTRICITY_PRICE_INDEX, GAS_PRICE_INDEX, DISCOUNT_RATE, retrofitting_scenario, FUEL_TYPE) global_capital_costs, global_capital_incomes = lcc.calculate_capital_costs() global_end_of_life_costs = lcc.calculate_end_of_life_costs() - global_operational_costs = lcc.calculate_total_operational_costs() + global_operational_costs = lcc.calculate_total_operational_costs global_maintenance_costs = lcc.calculate_total_maintenance_costs() global_operational_incomes = lcc.calculate_total_operational_incomes() full_path_output = Path(out_path / f'output {retrofitting_scenario} {building.name}.xlsx').resolve() @@ -151,8 +152,11 @@ for retrofitting_scenario in RETROFITTING_SCENARIOS: ) 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'] + df_capital_incomes = ( + global_capital_incomes['Subsidies construction'] + + global_capital_incomes['Subsidies HVAC'] + + global_capital_incomes['Subsidies PV'] + ) life_cycle_costs_capital_skin = _npv_from_list(DISCOUNT_RATE, df_capital_costs_skin.values.tolist()) life_cycle_costs_capital_systems = _npv_from_list(DISCOUNT_RATE, df_capital_costs_systems.values.tolist()) @@ -181,9 +185,12 @@ for retrofitting_scenario in RETROFITTING_SCENARIOS: life_cycle_capital_incomes] life_cycle_results.index = ['total_capital_costs_skin', - f'total_capital_costs_systems','end_of_life_costs', - 'total_operational_costs', 'total_maintenance_costs', - 'operational_incomes', 'capital_incomes'] + 'total_capital_costs_systems', + 'end_of_life_costs', + 'total_operational_costs', + 'total_maintenance_costs', + 'operational_incomes', + 'capital_incomes'] print(life_cycle_results) print(f'Scenario {retrofitting_scenario} {life_cycle_costs}') diff --git a/costs/life_cycle_costs.py b/costs/life_cycle_costs.py index c555334..c3624ca 100644 --- a/costs/life_cycle_costs.py +++ b/costs/life_cycle_costs.py @@ -64,6 +64,7 @@ class LifeCycleCosts: self._yearly_capital_incomes = pd.DataFrame(index=rng, columns=['Subsidies construction', 'Subsidies HVAC', 'Subsidies PV'], dtype='float') + def calculate_capital_costs(self): """ Calculate capital cost @@ -133,13 +134,11 @@ class LifeCycleCosts: capital_cost_roof = surface_roof * chapter.item('B3010_opaque_roof').refurbishment[0] capital_cost_ground = surface_ground * chapter.item('B10_superstructure').refurbishment[0] - self._yearly_capital_costs.loc[0, 'B2010_opaque_walls'] = capital_cost_opaque self._yearly_capital_costs.loc[0]['B2020_transparent'] = capital_cost_transparent self._yearly_capital_costs.loc[0, 'B3010_opaque_roof'] = capital_cost_roof self._yearly_capital_costs.loc[0]['B10_superstructure'] = capital_cost_ground - if self._retrofitting_scenario in (SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV): chapter = chapters.chapter('D_services') capital_cost_pv = surface_pv * chapter.item('D301010_photovoltaic_system').initial_investment[0] @@ -192,11 +191,16 @@ class LifeCycleCosts: * chapter.item( 'D301010_photovoltaic_system').reposition[0] * costs_increase capital_cost_skin = capital_cost_opaque + capital_cost_ground + capital_cost_transparent + capital_cost_roof - capital_cost_hvac = capital_cost_heating_equipment + capital_cost_cooling_equipment + \ - capital_cost_distribution_equipment + capital_cost_other_hvac_ahu + capital_cost_lighting + capital_cost_hvac = ( + capital_cost_heating_equipment + + capital_cost_cooling_equipment + + capital_cost_distribution_equipment + + capital_cost_other_hvac_ahu + capital_cost_lighting + ) - self._yearly_capital_incomes.loc[0, 'Subsidies construction'] = capital_cost_skin * \ - archetype.income.construction_subsidy/100 + self._yearly_capital_incomes.loc[0, 'Subsidies construction'] = ( + capital_cost_skin * archetype.income.construction_subsidy/100 + ) self._yearly_capital_incomes.loc[0, 'Subsidies HVAC'] = capital_cost_hvac * archetype.income.hvac_subsidy/100 self._yearly_capital_incomes.loc[0, 'Subsidies PV'] = capital_cost_pv * archetype.income.photovoltaic_subsidy/100 self._yearly_capital_incomes.fillna(0, inplace=True) @@ -210,7 +214,6 @@ class LifeCycleCosts: archetype = self._archetype total_floor_area = self._total_floor_area - price_increase = 0 for year in range(1, self._number_of_years + 1): price_increase = math.pow(1 + self._consumer_price_index, year) if year == self._number_of_years: @@ -219,6 +222,7 @@ class LifeCycleCosts: self._yearly_end_of_life_costs.fillna(0, inplace=True) return self._yearly_end_of_life_costs + @property def calculate_total_operational_costs(self): """ Calculate total operational costs @@ -289,21 +293,18 @@ class LifeCycleCosts: :return: pd.DataFrame """ building = self._building - archetype = self._archetype if cte.YEAR not in building.onsite_electrical_production: onsite_electricity_production = 0 else: onsite_electricity_production = building.onsite_electrical_production[cte.YEAR][0]/1000 - price_increase_electricity = 0 for year in range(1, self._number_of_years + 1): price_increase_electricity = math.pow(1 + self._electricity_price_index, year) - #todo: check the adequate assignation of price. Pilar - price_export = 0.075 # archetype.income.electricity_export - self._yearly_operational_incomes.loc[year, 'Incomes electricity'] = (onsite_electricity_production * - price_export * - price_increase_electricity - ) + # todo: check the adequate assignation of price. Pilar + price_export = 0.075 # archetype.income.electricity_export + self._yearly_operational_incomes.loc[year, 'Incomes electricity'] = ( + onsite_electricity_production * price_export * price_increase_electricity + ) self._yearly_operational_incomes.fillna(0, inplace=True) return self._yearly_operational_incomes