Merge pull request 'fix: different fuel pricings are added, operational and maintenance cost calculations are modified, cost catalogue adjusted to the changes' (#10) from costing_modification into main

Reviewed-on: https://nextgenerations-cities.encs.concordia.ca/gitea/s_ranjbar/energy_system_modelling_workflow/pulls/10
This commit is contained in:
Saeed Ranjbar 2024-06-20 09:42:43 -04:00 committed by s_ranjbar
commit 335b316072
19 changed files with 678 additions and 212 deletions

View File

@ -6,6 +6,7 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import xmltodict
import json
from hub.catalog_factories.catalog import Catalog
from hub.catalog_factories.data_models.cost.archetype import Archetype
from hub.catalog_factories.data_models.cost.content import Content
@ -15,6 +16,7 @@ from hub.catalog_factories.data_models.cost.item_description import ItemDescript
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.pricing_rate import PricingRate
class MontrealNewCatalog(Catalog):
@ -24,6 +26,7 @@ class MontrealNewCatalog(Catalog):
def __init__(self, path):
path = (path / 'montreal_costs_completed.xml').resolve()
self._fuel_rates_path = (path.parent / 'fuel_rates.json').resolve()
with open(path, 'r', encoding='utf-8') as xml:
self._archetypes = xmltodict.parse(xml.read(), force_list='archetype')
@ -75,7 +78,22 @@ class MontrealNewCatalog(Catalog):
refurbishment_unit=_refurbishment_unit,
reposition=None,
reposition_unit=None,
lifetime=None)
lifetime=None,
maintenance=None,
maintenance_unit=None)
elif 'maintenance_cost' in item.keys():
maintenance_cost = float(item['maintenance_cost']['#text'])
maintenance_unit = item['maintenance_cost']['@cost_unit']
_item_description = ItemDescription(item_type,
initial_investment=None,
initial_investment_unit=None,
refurbishment=None,
refurbishment_unit=None,
reposition=None,
reposition_unit=None,
lifetime=None,
maintenance=maintenance_cost,
maintenance_unit=maintenance_unit)
else:
_reposition = float(item['reposition']['#text'])
_reposition_unit = item['reposition']['@cost_unit']
@ -89,7 +107,9 @@ class MontrealNewCatalog(Catalog):
refurbishment_unit=None,
reposition=_reposition,
reposition_unit=_reposition_unit,
lifetime=_lifetime)
lifetime=_lifetime,
maintenance=None,
maintenance_unit=None)
return _item_description
@ -137,13 +157,35 @@ class MontrealNewCatalog(Catalog):
return capital_costs
@staticmethod
def _get_operational_costs(entry):
def load_fuel_rates(self):
rates = []
with open(self._fuel_rates_path, 'r') as f:
fuel_rates = json.load(f)
for rate in fuel_rates['rates']['fuels']['rate']:
name = rate['name']
rate_type = rate['rate_type']
units = rate['units']
values = rate['values']
rates.append(PricingRate(name=name, rate_type=rate_type, units=units, values=values))
return rates
def search_fuel_rates(self, rates, name):
variable = None
for rate in rates:
if rate.name == name:
variable = rate
return variable
def _get_operational_costs(self, entry):
fuels = []
rates = self.load_fuel_rates()
for item in entry['fuels']['fuel']:
fuel_type = item['@fuel_type']
fuel_variable = float(item['variable']['#text'])
fuel_variable_units = item['variable']['@cost_unit']
fuel_variable = item['variable']
variable = self.search_fuel_rates(rates, fuel_variable)
fuel_fixed_monthly = None
fuel_fixed_peak = None
density = None
@ -165,20 +207,22 @@ class MontrealNewCatalog(Catalog):
fuel = Fuel(fuel_type,
fixed_monthly=fuel_fixed_monthly,
fixed_power=fuel_fixed_peak,
variable=fuel_variable,
variable_units=fuel_variable_units,
variable=variable,
density=density,
density_unit=density_unit,
lower_heating_value=lower_heating_value,
lower_heating_value_unit=lower_heating_value_unit)
fuels.append(fuel)
heating_equipment_maintenance = float(entry['maintenance']['heating_equipment']['#text'])
cooling_equipment_maintenance = float(entry['maintenance']['cooling_equipment']['#text'])
hvac_equipment = entry['maintenance']['hvac_equipment']
items = []
for item in hvac_equipment:
items.append(self.item_description(item, hvac_equipment[item]))
photovoltaic_system_maintenance = float(entry['maintenance']['photovoltaic_system']['#text'])
co2_emissions = float(entry['co2_cost']['#text'])
_operational_cost = OperationalCost(fuels,
heating_equipment_maintenance,
cooling_equipment_maintenance,
items,
photovoltaic_system_maintenance,
co2_emissions)
return _operational_cost

View File

@ -6,7 +6,7 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
from typing import Union
from hub.catalog_factories.data_models.cost.pricing_rate import PricingRate
class Fuel:
"""
@ -16,7 +16,6 @@ class Fuel:
fixed_monthly=None,
fixed_power=None,
variable=None,
variable_units=None,
density=None,
density_unit=None,
lower_heating_value=None,
@ -26,7 +25,6 @@ class Fuel:
self._fixed_monthly = fixed_monthly
self._fixed_power = fixed_power
self._variable = variable
self._variable_units = variable_units
self._density = density
self._density_unit = density_unit
self._lower_heating_value = lower_heating_value
@ -59,12 +57,12 @@ class Fuel:
return None
@property
def variable(self) -> Union[tuple[None, None], tuple[float, str]]:
def variable(self) -> Union[None, PricingRate]:
"""
Get variable costs in given units
:return: None, None or float, str
"""
return self._variable, self._variable_units
return self._variable
@property
def density(self) -> Union[tuple[None, None], tuple[float, str]]:
@ -84,11 +82,13 @@ class Fuel:
def to_dictionary(self):
"""Class content to dictionary"""
variable_price = None
if self.variable is not None:
variable_price = self.variable.to_dictionary()
content = {'Fuel': {'fuel type': self.type,
'fixed operational costs [currency/month]': self.fixed_monthly,
'fixed operational costs depending on the peak power consumed [currency/month W]': self.fixed_power,
'variable operational costs': self.variable[0],
'units': self.variable[1],
'variable operational costs': variable_price,
'density': self.density[0],
'density unit': self.density[1],
'lower heating value': self.lower_heating_value[0],

View File

@ -19,7 +19,9 @@ class ItemDescription:
refurbishment_unit=None,
reposition=None,
reposition_unit=None,
lifetime=None):
lifetime=None,
maintenance=None,
maintenance_unit=None):
self._item_type = item_type
self._initial_investment = initial_investment
@ -29,6 +31,8 @@ class ItemDescription:
self._reposition = reposition
self._reposition_unit = reposition_unit
self._lifetime = lifetime
self._maintenance = maintenance
self._maintenance_unit = maintenance_unit
@property
def type(self):
@ -70,6 +74,14 @@ class ItemDescription:
"""
return self._lifetime
@property
def maintenance(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._maintenance, self._maintenance_unit
def to_dictionary(self):
"""Class content to dictionary"""
content = {'Item': {'type': self.type,
@ -79,7 +91,9 @@ class ItemDescription:
'refurbishment units': self.refurbishment[1],
'reposition': self.reposition[0],
'reposition units': self.reposition[1],
'life time [years]': self.lifetime
'life time [years]': self.lifetime,
'maintenance': self.maintenance[0],
'maintenance units': self.maintenance[1]
}
}

View File

@ -7,16 +7,15 @@ 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
from hub.catalog_factories.data_models.cost.item_description import ItemDescription
class OperationalCost:
"""
Operational cost class
"""
def __init__(self, fuels, maintenance_heating, maintenance_cooling, maintenance_pv, co2):
def __init__(self, fuels, maintenance_hvac, maintenance_pv, co2):
self._fuels = fuels
self._maintenance_heating = maintenance_heating
self._maintenance_cooling = maintenance_cooling
self._maintenance_hvac = maintenance_hvac
self._maintenance_pv = maintenance_pv
self._co2 = co2
@ -30,20 +29,12 @@ class OperationalCost:
return self._fuels
@property
def maintenance_heating(self):
def maintenance_hvac(self) -> List[ItemDescription]:
"""
Get cost of maintaining the heating system in currency/W
Get cost of maintaining the hvac system in currency/W
:return: float
"""
return self._maintenance_heating
@property
def maintenance_cooling(self):
"""
Get cost of maintaining the cooling system in currency/W
:return: float
"""
return self._maintenance_cooling
return self._maintenance_hvac
@property
def maintenance_pv(self):
@ -64,11 +55,13 @@ class OperationalCost:
def to_dictionary(self):
"""Class content to dictionary"""
_fuels = []
_hvac_maintenance = []
for _fuel in self.fuels:
_fuels.append(_fuel.to_dictionary())
for _hvac in self.maintenance_hvac:
_hvac_maintenance.append(_hvac.to_dictionary())
content = {'Maintenance': {'fuels': _fuels,
'cost of maintaining the heating system [currency/W]': self.maintenance_heating,
'cost of maintaining the cooling system [currency/W]': self.maintenance_cooling,
'cost of maintaining the hvac system [currency/W]': _hvac_maintenance,
'cost of maintaining the PV system [currency/W]': self.maintenance_pv,
'cost of CO2 emissions [currency/kgCO2]': self.co2
}

View File

@ -0,0 +1,62 @@
from typing import Union
class PricingRate:
def __init__(self, name=None, rate_type=None, time_range=None, units=None, values=None):
self._name = name
self._rate_type = rate_type
self._time_range = time_range
self._units = units
self._values = values
@property
def name(self):
"""
name of the rate
:return: str
"""
return self._name
@property
def rate_type(self):
"""
type of rate between fixed and variable
:return: str
"""
return self._rate_type
@property
def time_range(self) -> Union[None, str]:
"""
Get schedule time range from:
['minute', 'hour', 'day', 'week', 'month', 'year']
:return: None or str
"""
return self._time_range
@property
def units(self):
"""
get the consumption unit
:return: str
"""
return self._units
@property
def values(self):
"""
Get schedule values
:return: [Any]
"""
return self._values
def to_dictionary(self):
"""Class content to dictionary"""
content = {'Pricing': {'name': self.name,
'time range': self.time_range,
'type': self.rate_type,
'units': self.units,
'values': self.values}
}
return content

View File

@ -92,6 +92,7 @@ class Building(CityObject):
logging.error('Building %s [%s] has an unexpected surface type %s.', self.name, self.aliases, surface.type)
self._domestic_hot_water_peak_load = None
self._fuel_consumption_breakdown = {}
self._pv_generation = {}
@property
def shell(self) -> Polyhedron:
@ -450,8 +451,8 @@ class Building(CityObject):
monthly_values = PeakLoads(self).heating_peak_loads_from_methodology
if monthly_values is None:
return None
results[cte.MONTH] = [x for x in monthly_values]
results[cte.YEAR] = [max(monthly_values)]
results[cte.MONTH] = [x / cte.WATTS_HOUR_TO_JULES for x in monthly_values]
results[cte.YEAR] = [max(monthly_values) / cte.WATTS_HOUR_TO_JULES]
return results
@property
@ -467,8 +468,8 @@ class Building(CityObject):
monthly_values = PeakLoads(self).cooling_peak_loads_from_methodology
if monthly_values is None:
return None
results[cte.MONTH] = [x * cte.WATTS_HOUR_TO_JULES for x in monthly_values]
results[cte.YEAR] = [max(monthly_values)]
results[cte.MONTH] = [x / cte.WATTS_HOUR_TO_JULES for x in monthly_values]
results[cte.YEAR] = [max(monthly_values) / cte.WATTS_HOUR_TO_JULES]
return results
@property
@ -484,7 +485,7 @@ class Building(CityObject):
if monthly_values is None:
return None
results[cte.MONTH] = [x for x in monthly_values]
results[cte.YEAR] = [max(monthly_values)]
results[cte.YEAR] = [max(monthly_values) / cte.WATTS_HOUR_TO_JULES]
return results
@property
@ -911,3 +912,11 @@ class Building(CityObject):
fuel_breakdown[generation_system.fuel_type][cte.DOMESTIC_HOT_WATER] = self.domestic_hot_water_consumption[cte.YEAR][0]
self._fuel_consumption_breakdown = fuel_breakdown
return self._fuel_consumption_breakdown
@property
def pv_generation(self) -> dict:
return self._pv_generation
@pv_generation.setter
def pv_generation(self, value):
self._pv_generation = value

View File

@ -47,6 +47,7 @@ class Surface:
self._percentage_shared = None
self._solar_collectors_area_reduction_factor = None
self._global_irradiance_tilted = {}
self._installed_solar_collector_area = None
@property
def name(self):
@ -401,3 +402,19 @@ class Surface:
:param value: dict
"""
self._global_irradiance_tilted = value
@property
def installed_solar_collector_area(self):
"""
Get installed solar collector area in m2
:return: dict
"""
return self._installed_solar_collector_area
@installed_solar_collector_area.setter
def installed_solar_collector_area(self, value):
"""
Set installed solar collector area in m2
:return: dict
"""
self._installed_solar_collector_area = value

View File

@ -0,0 +1,106 @@
{
"rates": {
"fuels": {
"rate": [
{
"name": "Electricity-D",
"fuel_type": "Electricity",
"rate_name": "D",
"units": "CAD/kWh",
"usage_type": "residential",
"maximum_power_demand_kW": 65,
"rate_type": "fixed",
"notes": null,
"start_date": null,
"end_date": null,
"values": [
0.075
]
},
{
"name": "Electricity-Flex-D",
"fuel_type": "Electricity",
"rate_name": "Flex-D",
"units": "CAD/kWh",
"usage_type": "residential",
"maximum_power_demand_kW": 65,
"rate_type": "variable",
"notes": null,
"start_date": null,
"end_date": null,
"values": [
0.075,
0.075,
0.075,
0.075,
0.075,
0.075,
0.551,
0.551,
0.551,
0.075,
0.075,
0.075,
0.075,
0.075,
0.075,
0.075,
0.551,
0.551,
0.551,
0.551,
0.075,
0.075,
0.075,
0.075
]
},
{
"name": "Gas-Energir",
"fuel_type": "Gas",
"rate_name": null,
"units": "CAD/m3",
"usage_type": "residential",
"maximum_power_demand_kW": null,
"rate_type": "fixed",
"notes": null,
"start_date": null,
"end_date": null,
"values": [
0.4
]
},
{
"name": "Diesel-Fixed",
"fuel_type": "Diesel",
"rate_name": null,
"units": "CAD/l",
"usage_type": "residential",
"maximum_power_demand_kW": null,
"rate_type": "fixed",
"notes": null,
"start_date": null,
"end_date": null,
"values": [
1.2
]
},
{
"name": "Biomass-Fixed",
"fuel_type": "Biomass",
"rate_name": null,
"units": "CAD/kg",
"usage_type": "residential",
"maximum_power_demand_kW": null,
"rate_type": "fixed",
"notes": null,
"start_date": null,
"end_date": null,
"values": [
0.04
]
}
]
}
}
}

View File

@ -25,8 +25,8 @@
<D_services>
<D20_onsite_generation>
<D2010_photovoltaic_system>
<investment_cost cost_unit="currency/m2"> 0 </investment_cost>
<reposition cost_unit="currency/m2"> 0 </reposition>
<investment_cost cost_unit="currency/m2"> 300 </investment_cost>
<reposition cost_unit="currency/m2"> 300 </reposition>
<lifetime_equipment lifetime="years"> 25 </lifetime_equipment>
</D2010_photovoltaic_system>
</D20_onsite_generation>
@ -124,34 +124,58 @@
<operational_cost>
<fuels>
<fuel fuel_type="Electricity">
<fixed_monthly cost_unit="currency/month">12.27</fixed_monthly>
<fixed_power cost_unit="currency/month*kW">0</fixed_power>
<variable cost_unit="currency/kWh">0.075</variable>
<density/>
<lower_heating_value/>
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
<fixed_power cost_unit="currency/(month*kW)"> 0 </fixed_power>
<variable>Electricity-D</variable>
</fuel>
<fuel fuel_type="Electricity">
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
<fixed_power cost_unit="currency/(month*kW)"> 0 </fixed_power>
<variable>Electricity-Flex-D</variable>
</fuel>
<fuel fuel_type="Gas">
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
<variable cost_unit="currency/m3"> 0.4 </variable>
<variable>Gas-Energir</variable>
<density density_unit="kg/m3"> 0.777 </density>
<lower_heating_value lhv_unit="MJ/kg"> 47.1 </lower_heating_value>
</fuel>
<fuel fuel_type="Diesel">
<fixed_monthly/>
<variable cost_unit="currency/l"> 1.2 </variable>
<variable>Diesel-Fixed</variable>
<density density_unit="kg/l"> 0.846 </density>
<lower_heating_value lhv_unit="MJ/kg"> 42.6 </lower_heating_value>
</fuel>
<fuel fuel_type="Biomass">
<fixed_monthly/>
<variable cost_unit="currency/kg"> 0.04 </variable>
<variable>Biomass-Fixed</variable>
<density/>
<lower_heating_value lhv_unit="MJ/kg"> 18 </lower_heating_value>
</fuel>
</fuels>
<maintenance>
<heating_equipment cost_unit="currency/kW">40</heating_equipment>
<cooling_equipment cost_unit="currency/kW">40</cooling_equipment>
<hvac_equipment>
<air_source_heat_pump>
<maintenance_cost cost_unit="cureency/kW">100</maintenance_cost>
</air_source_heat_pump>
<ground_source_heat_pump>
<maintenance_cost cost_unit="cureency/kW">60</maintenance_cost>
</ground_source_heat_pump>
<water_source_heat_pump>
<maintenance_cost cost_unit="cureency/kW">50</maintenance_cost>
</water_source_heat_pump>
<gas_boiler>
<maintenance_cost cost_unit="cureency/kW">50</maintenance_cost>
</gas_boiler>
<electric_boiler>
<maintenance_cost cost_unit="cureency/kW">100</maintenance_cost>
</electric_boiler>
<general_heating_equipment>
<maintenance_cost cost_unit="cureency/kW">60</maintenance_cost>
</general_heating_equipment>
<general_cooling_equipment>
<maintenance_cost cost_unit="cureency/kW">50</maintenance_cost>
</general_cooling_equipment>
</hvac_equipment>
<photovoltaic_system cost_unit="currency/m2">1</photovoltaic_system>
</maintenance>
<co2_cost cost_unit="currency/kgCO2"> 30 </co2_cost>
@ -294,31 +318,57 @@
<fuel fuel_type="Electricity">
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
<fixed_power cost_unit="currency/(month*kW)"> 0 </fixed_power>
<variable cost_unit="currency/kWh"> 0.075 </variable>
<variable>Electricity-D</variable>
</fuel>
<fuel fuel_type="Electricity">
<fixed_monthly cost_unit="currency/month"> 12.27 </fixed_monthly>
<fixed_power cost_unit="currency/(month*kW)"> 0 </fixed_power>
<variable>Electricity-Flex-D</variable>
</fuel>
<fuel fuel_type="Gas">
<fixed_monthly cost_unit="currency/month"> 17.71 </fixed_monthly>
<variable cost_unit="currency/m3"> 0.0640 </variable>
<variable>Gas-Energir</variable>
<density density_unit="kg/m3"> 0.777 </density>
<lower_heating_value lhv_unit="MJ/kg"> 47.1 </lower_heating_value>
</fuel>
<fuel fuel_type="Diesel">
<fixed_monthly/>
<variable cost_unit="currency/l"> 1.2 </variable>
<variable>Diesel-Fixed</variable>
<density density_unit="kg/l"> 0.846 </density>
<lower_heating_value lhv_unit="MJ/kg"> 42.6 </lower_heating_value>
</fuel>
<fuel fuel_type="Biomass">
<fixed_monthly/>
<variable cost_unit="currency/kg"> 0.04 </variable>
<variable>Biomass-Fixed</variable>
<density/>
<lower_heating_value lhv_unit="MJ/kg"> 18 </lower_heating_value>
</fuel>
</fuels>
<maintenance>
<heating_equipment cost_unit="currency/kW">40</heating_equipment>
<cooling_equipment cost_unit="currency/kW">40</cooling_equipment>
<photovoltaic_system cost_unit="currency/m2">0</photovoltaic_system>
<hvac_equipment>
<air_source_heat_pump>
<maintenance_cost cost_unit="cureency/kW">100</maintenance_cost>
</air_source_heat_pump>
<ground_source_heat_pump>
<maintenance_cost cost_unit="cureency/kW">60</maintenance_cost>
</ground_source_heat_pump>
<water_source_heat_pump>
<maintenance_cost cost_unit="cureency/kW">50</maintenance_cost>
</water_source_heat_pump>
<gas_boiler>
<maintenance_cost cost_unit="cureency/kW">50</maintenance_cost>
</gas_boiler>
<electric_boiler>
<maintenance_cost cost_unit="cureency/kW">100</maintenance_cost>
</electric_boiler>
<general_heating_equipment>
<maintenance_cost cost_unit="cureency/kW">60</maintenance_cost>
</general_heating_equipment>
<general_cooling_equipment>
<maintenance_cost cost_unit="cureency/kW">50</maintenance_cost>
</general_cooling_equipment>
</hvac_equipment>
<photovoltaic_system cost_unit="currency/m2">1</photovoltaic_system>
</maintenance>
<co2_cost cost_unit="currency/kgCO2"> 30 </co2_cost>
</operational_cost>

45
main.py
View File

@ -1,45 +0,0 @@
from scripts.geojson_creator import process_geojson
from pathlib import Path
import subprocess
from scripts.ep_run_enrich import energy_plus_workflow
from hub.imports.geometry_factory import GeometryFactory
from hub.helpers.dictionaries import Dictionaries
from hub.imports.construction_factory import ConstructionFactory
from hub.imports.usage_factory import UsageFactory
from hub.imports.weather_factory import WeatherFactory
from hub.imports.results_factory import ResultFactory
from scripts.energy_system_analysis_report import EnergySystemAnalysisReport
from scripts import random_assignation
from hub.imports.energy_systems_factory import EnergySystemsFactory
from scripts.energy_system_sizing import SystemSizing
from scripts.energy_system_retrofit_results import system_results, new_system_results
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
from scripts.costs.cost import Cost
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV
import hub.helpers.constants as cte
from hub.exports.exports_factory import ExportsFactory
# Specify the GeoJSON file path
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
file_path = (Path(__file__).parent / 'input_files' / 'output_buildings.geojson')
# Specify the output path for the PDF file
output_path = (Path(__file__).parent / 'out_files').resolve()
# Create city object from GeoJSON file
city = GeometryFactory('geojson',
path=file_path,
height_field='height',
year_of_construction_field='year_of_construction',
function_field='function',
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
# Enrich city data
ConstructionFactory('nrcan', city).enrich()
UsageFactory('nrcan', city).enrich()
WeatherFactory('epw', city).enrich()
energy_plus_workflow(city)
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
EnergySystemsFactory('montreal_future', city).enrich()
for building in city.buildings:
EnergySystemsSimulationFactory('archetype13', building=building, output_path=output_path).enrich()
print('test')

View File

@ -12,7 +12,8 @@ import numpy_financial as npf
from hub.city_model_structure.building import Building
import hub.helpers.constants as cte
from scripts.costs.configuration import Configuration
from scripts.costs.constants import SKIN_RETROFIT, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV
from scripts.costs.constants import (SKIN_RETROFIT, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV,
SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS, PV)
from scripts.costs.cost_base import CostBase
@ -36,7 +37,6 @@ class CapitalCosts(CostBase):
'D3050_other_hvac_ahu',
'D3060_storage_systems',
'D40_dhw',
'D5020_lighting_and_branch_wiring'
],
dtype='float'
)
@ -50,7 +50,6 @@ class CapitalCosts(CostBase):
self._yearly_capital_costs.loc[0, 'D3080_other_hvac_ahu'] = 0
self._yearly_capital_costs.loc[0, 'D3060_storage_systems'] = 0
self._yearly_capital_costs.loc[0, 'D40_dhw'] = 0
# self._yearly_capital_costs.loc[0, 'D5020_lighting_and_branch_wiring'] = 0
self._yearly_capital_incomes = pd.DataFrame(
index=self._rng,
@ -70,12 +69,14 @@ class CapitalCosts(CostBase):
for roof in self._building.roofs:
self._surface_pv += roof.solid_polygon.area * roof.solar_collectors_area_reduction_factor
for roof in self._building.roofs:
if roof.installed_solar_collector_area is not None:
self._surface_pv += roof.installed_solar_collector_area
else:
self._surface_pv += roof.solid_polygon.area * roof.solar_collectors_area_reduction_factor
def calculate(self) -> tuple[pd.DataFrame, pd.DataFrame]:
if self._configuration.retrofit_scenario in (SKIN_RETROFIT, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV):
self.skin_capital_cost()
if self._configuration.retrofit_scenario in (SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV):
self.energy_system_capital_cost()
self.skin_capital_cost()
self.energy_system_capital_cost()
self.skin_yearly_capital_costs()
self.yearly_energy_system_costs()
self.yearly_incomes()
@ -106,10 +107,11 @@ class CapitalCosts(CostBase):
capital_cost_transparent = surface_transparent * chapter.item('B2020_transparent').refurbishment[0]
capital_cost_roof = surface_roof * chapter.item('B3010_opaque_roof').refurbishment[0]
capital_cost_ground = surface_ground * chapter.item('B1010_superstructure').refurbishment[0]
self._yearly_capital_costs.loc[0, 'B2010_opaque_walls'] = capital_cost_opaque * self._own_capital
self._yearly_capital_costs.loc[0, 'B2020_transparent'] = capital_cost_transparent * self._own_capital
self._yearly_capital_costs.loc[0, 'B3010_opaque_roof'] = capital_cost_roof * self._own_capital
self._yearly_capital_costs.loc[0, 'B1010_superstructure'] = capital_cost_ground * self._own_capital
if self._configuration.retrofit_scenario not in (SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS, PV):
self._yearly_capital_costs.loc[0, 'B2010_opaque_walls'] = capital_cost_opaque * self._own_capital
self._yearly_capital_costs.loc[0, 'B2020_transparent'] = capital_cost_transparent * self._own_capital
self._yearly_capital_costs.loc[0, 'B3010_opaque_roof'] = capital_cost_roof * self._own_capital
self._yearly_capital_costs.loc[0, 'B1010_superstructure'] = capital_cost_ground * self._own_capital
capital_cost_skin = capital_cost_opaque + capital_cost_ground + capital_cost_transparent + capital_cost_roof
return capital_cost_opaque, capital_cost_transparent, capital_cost_roof, capital_cost_ground, capital_cost_skin
@ -147,18 +149,13 @@ class CapitalCosts(CostBase):
def energy_system_capital_cost(self):
chapter = self._capital_costs_chapter.chapter('D_services')
energy_system_components = self.system_components()
system_components = energy_system_components[0]
component_categories = energy_system_components[1]
component_sizes = energy_system_components[-1]
system_components, component_categories, component_sizes = self.system_components()
capital_cost_heating_and_cooling_equipment = 0
capital_cost_domestic_hot_water_equipment = 0
capital_cost_energy_storage_equipment = 0
capital_cost_distribution_equipment = 0
capital_cost_lighting = 0
capital_cost_pv = self._surface_pv * chapter.item('D2010_photovoltaic_system').initial_investment[0]
# capital_cost_lighting = self._total_floor_area * \
# chapter.item('D5020_lighting_and_branch_wiring').initial_investment[0]
for (i, component) in enumerate(system_components):
if component_categories[i] == 'generation':
capital_cost_heating_and_cooling_equipment += chapter.item(component).initial_investment[0] * component_sizes[i]
@ -171,26 +168,31 @@ class CapitalCosts(CostBase):
else:
capital_cost_energy_storage_equipment += chapter.item(component).initial_investment[0] * component_sizes[i]
self._yearly_capital_costs.loc[0, 'D2010_photovoltaic_system'] = capital_cost_pv
self._yearly_capital_costs.loc[0, 'D3020_heat_and_cooling_generating_systems'] = (
capital_cost_heating_and_cooling_equipment * self._own_capital)
self._yearly_capital_costs.loc[0, 'D3040_distribution_systems'] = (
capital_cost_distribution_equipment * self._own_capital)
self._yearly_capital_costs.loc[0, 'D3060_storage_systems'] = (
capital_cost_energy_storage_equipment * self._own_capital)
self._yearly_capital_costs.loc[0, 'D40_dhw'] = (
capital_cost_domestic_hot_water_equipment * self._own_capital)
# self._yearly_capital_costs.loc[0, 'D5020_lighting_and_branch_wiring'] = capital_cost_lighting * self._own_capital
capital_cost_hvac = capital_cost_heating_and_cooling_equipment + capital_cost_distribution_equipment + capital_cost_energy_storage_equipment + capital_cost_domestic_hot_water_equipment
if self._configuration.retrofit_scenario in (SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, PV):
self._yearly_capital_costs.loc[0, 'D2010_photovoltaic_system'] = capital_cost_pv
if self._configuration.retrofit_scenario in (SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV):
self._yearly_capital_costs.loc[0, 'D3020_heat_and_cooling_generating_systems'] = (
capital_cost_heating_and_cooling_equipment * self._own_capital)
self._yearly_capital_costs.loc[0, 'D3040_distribution_systems'] = (
capital_cost_distribution_equipment * self._own_capital)
self._yearly_capital_costs.loc[0, 'D3060_storage_systems'] = (
capital_cost_energy_storage_equipment * self._own_capital)
self._yearly_capital_costs.loc[0, 'D40_dhw'] = (
capital_cost_domestic_hot_water_equipment * self._own_capital)
capital_cost_hvac = (capital_cost_heating_and_cooling_equipment + capital_cost_distribution_equipment +
capital_cost_energy_storage_equipment + capital_cost_domestic_hot_water_equipment)
return (capital_cost_pv, capital_cost_heating_and_cooling_equipment, capital_cost_distribution_equipment,
capital_cost_energy_storage_equipment, capital_cost_domestic_hot_water_equipment, capital_cost_lighting, capital_cost_hvac)
def yearly_energy_system_costs(self):
chapter = self._capital_costs_chapter.chapter('D_services')
system_investment_costs = self.energy_system_capital_cost()
system_components = self.system_components()[0]
component_categories = self.system_components()[1]
component_sizes = self.system_components()[2]
system_components, component_categories, component_sizes = self.system_components()
pv = False
for energy_system in self._building.energy_systems:
for generation_system in energy_system.generation_systems:
if generation_system.system_type == cte.PHOTOVOLTAIC:
pv = True
for year in range(1, self._configuration.number_of_years):
costs_increase = math.pow(1 + self._configuration.consumer_price_index, year)
self._yearly_capital_costs.loc[year, 'D2010_photovoltaic_system'] = (
@ -228,23 +230,7 @@ class CapitalCosts(CostBase):
system_investment_costs[4] * self._configuration.percentage_credit
)
)
# self._yearly_capital_costs.loc[year, 'D5020_lighting_and_branch_wiring'] = (
# -npf.pmt(
# self._configuration.interest_rate,
# self._configuration.credit_years,
# system_investment_costs[5] * self._configuration.percentage_credit
# )
# )
# if (year % chapter.item('D5020_lighting_and_branch_wiring').lifetime) == 0:
# reposition_cost_lighting = (
# self._total_floor_area * chapter.item('D5020_lighting_and_branch_wiring').reposition[0] * costs_increase
# )
# self._yearly_capital_costs.loc[year, 'D5020_lighting_and_branch_wiring'] += reposition_cost_lighting
if self._configuration.retrofit_scenario in (SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV):
if (year % chapter.item('D2010_photovoltaic_system').lifetime) == 0:
self._yearly_capital_costs.loc[year, 'D2010_photovoltaic_system'] += (
self._surface_pv * chapter.item('D2010_photovoltaic_system').reposition[0] * costs_increase
)
if self._configuration.retrofit_scenario not in (SKIN_RETROFIT, PV):
for (i, component) in enumerate(system_components):
if (year % chapter.item(component).lifetime) == 0 and year != (self._configuration.number_of_years - 1):
if component_categories[i] == 'generation':
@ -259,6 +245,17 @@ class CapitalCosts(CostBase):
else:
reposition_cost_energy_storage_equipment = chapter.item(component).initial_investment[0] * component_sizes[i] * costs_increase
self._yearly_capital_costs.loc[year, 'D3060_storage_systems'] += reposition_cost_energy_storage_equipment
if self._configuration.retrofit_scenario == CURRENT_STATUS and pv:
if (year % chapter.item('D2010_photovoltaic_system').lifetime) == 0:
self._yearly_capital_costs.loc[year, 'D2010_photovoltaic_system'] += (
self._surface_pv * chapter.item('D2010_photovoltaic_system').reposition[0] * costs_increase
)
elif self._configuration.retrofit_scenario in (PV, SYSTEM_RETROFIT_AND_PV,
SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV):
if (year % chapter.item('D2010_photovoltaic_system').lifetime) == 0:
self._yearly_capital_costs.loc[year, 'D2010_photovoltaic_system'] += (
self._surface_pv * chapter.item('D2010_photovoltaic_system').reposition[0] * costs_increase
)
def system_components(self):
system_components = []
@ -308,7 +305,7 @@ class CapitalCosts(CostBase):
if distribution_systems is not None:
for distribution_system in distribution_systems:
component_categories.append('distribution')
sizes.append(self._building.cooling_peak_load[cte.YEAR][0] / 3.6e6)
sizes.append(self._building.cooling_peak_load[cte.YEAR][0] / 1000)
system_components.append('D3040_distribution_systems')
return system_components, component_categories, sizes

View File

@ -28,7 +28,8 @@ class Configuration:
factories_handler,
retrofit_scenario,
fuel_type,
dictionary
dictionary,
fuel_tariffs
):
self._number_of_years = number_of_years
self._percentage_credit = percentage_credit
@ -45,6 +46,7 @@ class Configuration:
self._retrofit_scenario = retrofit_scenario
self._fuel_type = fuel_type
self._dictionary = dictionary
self._fuel_tariffs = fuel_tariffs
@property
def number_of_years(self):
@ -227,3 +229,10 @@ class Configuration:
Get hub function to cost function dictionary
"""
return self._dictionary
@property
def fuel_tariffs(self):
"""
Get fuel tariffs
"""
return self._fuel_tariffs

View File

@ -11,9 +11,11 @@ CURRENT_STATUS = 0
SKIN_RETROFIT = 1
SYSTEM_RETROFIT_AND_PV = 2
SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV = 3
PV = 4
RETROFITTING_SCENARIOS = [
CURRENT_STATUS,
SKIN_RETROFIT,
SYSTEM_RETROFIT_AND_PV,
SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV
SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV,
PV
]

View File

@ -40,7 +40,10 @@ class Cost:
retrofitting_year_construction=2020,
factories_handler='montreal_new',
retrofit_scenario=CURRENT_STATUS,
dictionary=None):
dictionary=None,
fuel_tariffs=None):
if fuel_tariffs is None:
fuel_tariffs = ['Electricity-D', 'Gas-Energir']
if dictionary is None:
dictionary = Dictionaries().hub_function_to_montreal_custom_costs_function
self._building = building
@ -57,7 +60,8 @@ class Cost:
factories_handler,
retrofit_scenario,
fuel_type,
dictionary)
dictionary,
fuel_tariffs)
@property
def building(self) -> Building:
@ -94,7 +98,6 @@ class Cost:
global_capital_costs['D3050_other_hvac_ahu'] +
global_capital_costs['D3060_storage_systems'] +
global_capital_costs['D40_dhw'] +
global_capital_costs['D5020_lighting_and_branch_wiring'] +
global_capital_costs['D2010_photovoltaic_system']
)

View File

@ -45,7 +45,7 @@ class PeakLoad:
conditioning_peak[i] = self._building.heating_peak_load[cte.MONTH][i] * heating
else:
conditioning_peak[i] = self._building.cooling_peak_load[cte.MONTH][i] * cooling
monthly_electricity_peak[i] += 0.8 * conditioning_peak[i] / 3600
monthly_electricity_peak[i] += 0.8 * conditioning_peak[i]
electricity_peak_load_results = pd.DataFrame(
monthly_electricity_peak,

View File

@ -25,6 +25,7 @@ class TotalMaintenanceCosts(CostBase):
columns=[
'Heating_maintenance',
'Cooling_maintenance',
'DHW_maintenance',
'PV_maintenance'
],
dtype='float'
@ -39,15 +40,76 @@ class TotalMaintenanceCosts(CostBase):
archetype = self._archetype
# todo: change area pv when the variable exists
roof_area = 0
for roof in building.roofs:
roof_area += roof.solid_polygon.area
surface_pv = roof_area * 0.5
surface_pv = 0
for roof in self._building.roofs:
if roof.installed_solar_collector_area is not None:
surface_pv += roof.installed_solar_collector_area
else:
surface_pv = roof_area * 0.5
peak_heating = building.heating_peak_load[cte.YEAR][0] / 3.6e6
peak_cooling = building.cooling_peak_load[cte.YEAR][0] / 3.6e6
energy_systems = building.energy_systems
maintenance_heating_0 = 0
maintenance_cooling_0 = 0
maintenance_dhw_0 = 0
heating_equipments = {}
cooling_equipments = {}
dhw_equipments = {}
for energy_system in energy_systems:
if cte.COOLING in energy_system.demand_types:
for generation_system in energy_system.generation_systems:
if generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.AIR:
cooling_equipments['air_source_heat_pump'] = generation_system.nominal_cooling_output / 1000
elif generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.GROUND:
cooling_equipments['ground_source_heat_pump'] = generation_system.nominal_cooling_output / 1000
elif generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.WATER:
cooling_equipments['water_source_heat_pump'] = generation_system.nominal_cooling_output / 1000
else:
cooling_equipments['general_cooling_equipment'] = generation_system.nominal_cooling_output / 1000
if cte.HEATING in energy_system.demand_types:
for generation_system in energy_system.generation_systems:
if generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.AIR:
heating_equipments['air_source_heat_pump'] = generation_system.nominal_heat_output / 1000
elif generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.GROUND:
heating_equipments['ground_source_heat_pump'] = generation_system.nominal_heat_output / 1000
elif generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.WATER:
heating_equipments['water_source_heat_pump'] = generation_system.nominal_heat_output / 1000
elif generation_system.system_type == cte.BOILER and generation_system.fuel_type == cte.GAS:
heating_equipments['gas_boiler'] = generation_system.nominal_heat_output / 1000
elif generation_system.system_type == cte.BOILER and generation_system.fuel_type == cte.ELECTRICITY:
heating_equipments['electric_boiler'] = generation_system.nominal_heat_output / 1000
else:
heating_equipments['general_heating_equipment'] = generation_system.nominal_heat_output / 1000
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types and cte.HEATING not in energy_system.demand_types:
for generation_system in energy_system.generation_systems:
if generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.AIR:
dhw_equipments['air_source_heat_pump'] = generation_system.nominal_heat_output / 1000
elif generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.GROUND:
dhw_equipments['ground_source_heat_pump'] = generation_system.nominal_heat_output / 1000
elif generation_system.system_type == cte.HEAT_PUMP and generation_system.source_medium == cte.WATER:
dhw_equipments['water_source_heat_pump'] = generation_system.nominal_heat_output / 1000
elif generation_system.system_type == cte.BOILER and generation_system.fuel_type == cte.GAS:
dhw_equipments['gas_boiler'] = generation_system.nominal_heat_output / 1000
elif generation_system.system_type == cte.BOILER and generation_system.fuel_type == cte.ELECTRICITY:
dhw_equipments['electric_boiler'] = generation_system.nominal_heat_output / 1000
else:
dhw_equipments['general_heating_equipment'] = generation_system.nominal_heat_output / 1000
for heating_equipment in heating_equipments:
component = self.search_hvac_equipment(heating_equipment)
maintenance_cost = component.maintenance[0]
maintenance_heating_0 += (heating_equipments[heating_equipment] * maintenance_cost)
for cooling_equipment in cooling_equipments:
component = self.search_hvac_equipment(cooling_equipment)
maintenance_cost = component.maintenance[0]
maintenance_cooling_0 += (cooling_equipments[cooling_equipment] * maintenance_cost)
for dhw_equipment in dhw_equipments:
component = self.search_hvac_equipment(dhw_equipment)
maintenance_cost = component.maintenance[0]
maintenance_dhw_0 += (dhw_equipments[dhw_equipment] * maintenance_cost)
maintenance_heating_0 = peak_heating * archetype.operational_cost.maintenance_heating
maintenance_cooling_0 = peak_cooling * archetype.operational_cost.maintenance_cooling
maintenance_pv_0 = surface_pv * archetype.operational_cost.maintenance_pv
for year in range(1, self._configuration.number_of_years + 1):
@ -58,8 +120,18 @@ class TotalMaintenanceCosts(CostBase):
self._yearly_maintenance_costs.loc[year, 'Cooling_maintenance'] = (
maintenance_cooling_0 * costs_increase
)
self._yearly_maintenance_costs.loc[year, 'DHW_maintenance'] = (
maintenance_dhw_0 * costs_increase
)
self._yearly_maintenance_costs.loc[year, 'PV_maintenance'] = (
maintenance_pv_0 * costs_increase
)
self._yearly_maintenance_costs.fillna(0, inplace=True)
return self._yearly_maintenance_costs
def search_hvac_equipment(self, equipment_type):
for component in self._archetype.operational_cost.maintenance_hvac:
if component.type == equipment_type:
return component

View File

@ -42,48 +42,68 @@ class TotalOperationalCosts(CostBase):
factor = total_floor_area / 80
else:
factor = 1
total_electricity_consumption = sum(self._building.energy_consumption_breakdown[cte.ELECTRICITY].values())
total_electricity_consumption = sum(self._building.energy_consumption_breakdown[cte.ELECTRICITY].values()) / 3600
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:
for system_fuel in self._configuration.fuel_type:
fuel = None
for fuel_tariff in self._configuration.fuel_tariffs:
if system_fuel in fuel_tariff:
fuel = self.search_fuel(system_fuel, fuel_tariff)
if fuel.type == cte.ELECTRICITY:
if fuel.variable.rate_type == 'fixed':
variable_electricity_cost_year_0 = (
total_electricity_consumption * fuel.variable[0] / 1000
total_electricity_consumption * float(fuel.variable.values[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
hourly_electricity_consumption = self.hourly_fuel_consumption_profile(fuel.type)
hourly_electricity_price_profile = fuel.variable.values * len(hourly_electricity_consumption)
hourly_electricity_price = [hourly_electricity_consumption[i] / 1000 * hourly_electricity_price_profile[i]
for i in range(len(hourly_electricity_consumption))]
variable_electricity_cost_year_0 = sum(hourly_electricity_price)
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:
conversion_factor = fuel.density[0]
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]
if fuel.variable.rate_type == 'fixed':
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)
(sum(fuel_consumption_breakdown[fuel.type].values()) / (
1e6 * fuel.lower_heating_value[0] * conversion_factor)) * fuel.variable.values[0])
else:
hourly_fuel_consumption = self.hourly_fuel_consumption_profile(fuel.type)
hourly_fuel_price_profile = fuel.variable.values * len(hourly_fuel_consumption)
hourly_fuel_price = [hourly_fuel_consumption[i] / (
1e6 * fuel.lower_heating_value[0] * conversion_factor) * hourly_fuel_price_profile[i]
for i in range(len(hourly_fuel_consumption))]
variable_cost_fuel = sum(hourly_fuel_price)
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
@ -102,3 +122,116 @@ class TotalOperationalCosts(CostBase):
return columns_list
def search_fuel(self, system_fuel, tariff):
fuels = self._archetype.operational_cost.fuels
for fuel in fuels:
if system_fuel == fuel.type and tariff == fuel.variable.name:
return fuel
raise KeyError(f'fuel {system_fuel} with {tariff} tariff not found')
def hourly_fuel_consumption_profile(self, fuel_type):
hourly_fuel_consumption = []
energy_systems = self._building.energy_systems
if fuel_type == cte.ELECTRICITY:
appliance = self._building.appliances_electrical_demand[cte.HOUR]
lighting = self._building.lighting_electrical_demand[cte.HOUR]
elec_heating = 0
elec_cooling = 0
elec_dhw = 0
if cte.HEATING in self._building.energy_consumption_breakdown[cte.ELECTRICITY]:
elec_heating = 1
if cte.COOLING in self._building.energy_consumption_breakdown[cte.ELECTRICITY]:
elec_cooling = 1
if cte.DOMESTIC_HOT_WATER in self._building.energy_consumption_breakdown[cte.ELECTRICITY]:
elec_dhw = 1
heating = None
cooling = None
dhw = None
if elec_heating == 1:
for energy_system in energy_systems:
if cte.HEATING in energy_system.demand_types:
for generation_system in energy_system.generation_systems:
if generation_system.fuel_type == cte.ELECTRICITY:
if cte.HEATING in generation_system.energy_consumption:
heating = generation_system.energy_consumption[cte.HEATING][cte.HOUR]
else:
if len(energy_system.generation_systems) > 1:
heating = [x / 2 for x in self._building.heating_consumption[cte.HOUR]]
else:
heating = self._building.heating_consumption[cte.HOUR]
if elec_dhw == 1:
for energy_system in energy_systems:
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
for generation_system in energy_system.generation_systems:
if generation_system.fuel_type == cte.ELECTRICITY:
if cte.DOMESTIC_HOT_WATER in generation_system.energy_consumption:
dhw = generation_system.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR]
else:
if len(energy_system.generation_systems) > 1:
dhw = [x / 2 for x in self._building.domestic_hot_water_consumption[cte.HOUR]]
else:
dhw = self._building.domestic_hot_water_consumption[cte.HOUR]
if elec_cooling == 1:
for energy_system in energy_systems:
if cte.COOLING in energy_system.demand_types:
for generation_system in energy_system.generation_systems:
if cte.COOLING in generation_system.energy_consumption:
cooling = generation_system.energy_consumption[cte.COOLING][cte.HOUR]
else:
if len(energy_system.generation_systems) > 1:
cooling = [x / 2 for x in self._building.cooling_consumption[cte.HOUR]]
else:
cooling = self._building.cooling_consumption[cte.HOUR]
for i in range(len(self._building.heating_demand[cte.HOUR])):
hourly = 0
hourly += appliance[i] / 3600
hourly += lighting[i] / 3600
if heating is not None:
hourly += heating[i] / 3600
if cooling is not None:
hourly += cooling[i] / 3600
if dhw is not None:
dhw += dhw[i] / 3600
hourly_fuel_consumption.append(hourly)
else:
heating = None
dhw = None
if cte.HEATING in self._building.energy_consumption_breakdown[fuel_type]:
for energy_system in energy_systems:
if cte.HEATING in energy_system.demand_types:
for generation_system in energy_system.generation_systems:
if cte.HEATING in generation_system.energy_consumption:
heating = generation_system.energy_consumption[cte.HEATING][cte.HOUR]
else:
if len(energy_system.generation_systems) > 1:
heating = [x / 2 for x in self._building.heating_consumption[cte.HOUR]]
else:
heating = self._building.heating_consumption[cte.HOUR]
if cte.DOMESTIC_HOT_WATER in self._building.energy_consumption_breakdown[fuel_type]:
for energy_system in energy_systems:
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
for generation_system in energy_system.generation_systems:
if cte.DOMESTIC_HOT_WATER in generation_system.energy_consumption:
dhw = generation_system.energy_consumption[cte.DOMESTIC_HOT_WATER][cte.HOUR]
else:
if len(energy_system.generation_systems) > 1:
dhw = [x / 2 for x in self._building.domestic_hot_water_consumption[cte.HOUR]]
else:
dhw = self._building.domestic_hot_water_consumption[cte.HOUR]
for i in range(len(self._building.heating_demand[cte.HOUR])):
hourly = 0
if heating is not None:
hourly += heating[i] / 3600
if dhw is not None:
hourly += dhw[i] / 3600
hourly_fuel_consumption.append(hourly)
return hourly_fuel_consumption

View File

@ -52,17 +52,17 @@ class SystemSizing:
if cte.HEATING in demand_types:
if len(generation_systems) == 1:
for generation in generation_systems:
generation.nominal_heat_output = building.heating_peak_load[cte.YEAR][0] / 3600
generation.nominal_heat_output = building.heating_peak_load[cte.YEAR][0]
else:
for generation in generation_systems:
generation.nominal_heat_output = building.heating_peak_load[cte.YEAR][0] / (len(generation_systems) * 3600)
generation.nominal_heat_output = building.heating_peak_load[cte.YEAR][0] / (len(generation_systems))
elif cte.COOLING in demand_types:
if len(generation_systems) == 1:
for generation in generation_systems:
generation.nominal_cooling_output = building.cooling_peak_load[cte.YEAR][0] / 3600
generation.nominal_cooling_output = building.cooling_peak_load[cte.YEAR][0]
else:
for generation in generation_systems:
generation.nominal_heat_output = building.cooling_peak_load[cte.YEAR][0] / (len(generation_systems) * 3600)
generation.nominal_heat_output = building.cooling_peak_load[cte.YEAR][0] / (len(generation_systems))

View File

@ -15,8 +15,8 @@ from hub.city_model_structure.building import Building
energy_systems_format = 'montreal_custom'
# parameters:
residential_systems_percentage = {'system 1 gas': 44,
'system 1 electricity': 6,
residential_systems_percentage = {'system 1 gas': 100,
'system 1 electricity': 0,
'system 2 gas': 0,
'system 2 electricity': 0,
'system 3 and 4 gas': 0,
@ -25,8 +25,8 @@ residential_systems_percentage = {'system 1 gas': 44,
'system 5 electricity': 0,
'system 6 gas': 0,
'system 6 electricity': 0,
'system 8 gas': 44,
'system 8 electricity': 6}
'system 8 gas': 0,
'system 8 electricity': 0}
residential_new_systems_percentage = {'PV+ASHP+GasBoiler+TES': 0,
'PV+4Pipe+DHW': 100,