CityBEM-CityLayers-SaeedRay.../scripts/costs/total_operational_costs.py

105 lines
4.5 KiB
Python

"""
Total operational costs module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2024 Project Coder Saeed Ranjbar saeed.ranjbar@mail.concordia.ca
Code contributor Oriol Gavalda Torrellas oriol.gavalda@concordia.ca
"""
import math
import pandas as pd
from hub.city_model_structure.building import Building
import hub.helpers.constants as cte
from scripts.costs.configuration import Configuration
from scripts.costs.cost_base import CostBase
from scripts.costs.peak_load import PeakLoad
class TotalOperationalCosts(CostBase):
"""
Total Operational costs class
"""
def __init__(self, building: Building, configuration: Configuration):
super().__init__(building, configuration)
columns_list = self.columns()
self._yearly_operational_costs = pd.DataFrame(
index=self._rng,
columns=columns_list,
dtype='float'
)
def calculate(self) -> pd.DataFrame:
"""
Calculate total operational costs
:return: pd.DataFrame
"""
building = self._building
fuel_consumption_breakdown = building.energy_consumption_breakdown
archetype = self._archetype
total_floor_area = self._total_floor_area
if archetype.function == 'residential':
factor = total_floor_area / 80
else:
factor = 1
total_electricity_consumption = sum(self._building.energy_consumption_breakdown[cte.ELECTRICITY].values())
peak_electricity_load = PeakLoad(self._building).electricity_peak_load
peak_load_value = peak_electricity_load.max(axis=1)
peak_electricity_demand = peak_load_value[1] / 1000 # self._peak_electricity_demand adapted to kW
fuels = archetype.operational_cost.fuels
for fuel in fuels:
if fuel.type in fuel_consumption_breakdown.keys():
if fuel.type == cte.ELECTRICITY:
variable_electricity_cost_year_0 = (
total_electricity_consumption * fuel.variable[0] / 1000
)
peak_electricity_cost_year_0 = peak_electricity_demand * fuel.fixed_power * 12
monthly_electricity_cost_year_0 = fuel.fixed_monthly * 12 * factor
for year in range(1, self._configuration.number_of_years + 1):
price_increase_electricity = math.pow(1 + self._configuration.electricity_price_index, year)
price_increase_peak_electricity = math.pow(1 + self._configuration.electricity_peak_index, year)
self._yearly_operational_costs.at[year, 'Fixed Costs Electricity Peak'] = (
peak_electricity_cost_year_0 * price_increase_peak_electricity
)
self._yearly_operational_costs.at[year, 'Fixed Costs Electricity Monthly'] = (
monthly_electricity_cost_year_0 * price_increase_peak_electricity
)
if not isinstance(variable_electricity_cost_year_0, pd.DataFrame):
variable_costs_electricity = variable_electricity_cost_year_0 * price_increase_electricity
else:
variable_costs_electricity = float(variable_electricity_cost_year_0.iloc[0] * price_increase_electricity)
self._yearly_operational_costs.at[year, 'Variable Costs Electricity'] = (
variable_costs_electricity
)
else:
fuel_fixed_cost = fuel.fixed_monthly * 12 * factor
if fuel.type == cte.BIOMASS:
conversion_factor = 1
else:
conversion_factor = fuel.density[0]
variable_cost_fuel = (
((sum(fuel_consumption_breakdown[fuel.type].values()) * 3600)/(1e6*fuel.lower_heating_value[0] * conversion_factor)) * fuel.variable[0])
for year in range(1, self._configuration.number_of_years + 1):
price_increase_gas = math.pow(1 + self._configuration.gas_price_index, year)
self._yearly_operational_costs.at[year, f'Fixed Costs {fuel.type}'] = fuel_fixed_cost * price_increase_gas
self._yearly_operational_costs.at[year, f'Variable Costs {fuel.type}'] = (
variable_cost_fuel * price_increase_gas)
self._yearly_operational_costs.fillna(0, inplace=True)
return self._yearly_operational_costs
def columns(self):
columns_list = []
fuels = [key for key in self._building.energy_consumption_breakdown.keys()]
for fuel in fuels:
if fuel == cte.ELECTRICITY:
columns_list.append('Fixed Costs Electricity Peak')
columns_list.append('Fixed Costs Electricity Monthly')
columns_list.append('Variable Costs Electricity')
else:
columns_list.append(f'Fixed Costs {fuel}')
columns_list.append(f'Variable Costs {fuel}')
return columns_list