fix: The report is almost completed. It will be continued after fixing all the simulation models
This commit is contained in:
parent
c4f98a30c1
commit
f32c74f84a
@ -1,4 +1,3 @@
|
||||
from scripts.geojson_creator import process_geojson
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from scripts.ep_run_enrich import energy_plus_workflow
|
||||
@ -8,57 +7,92 @@ 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.energy_system_retrofit_report import EnergySystemRetrofitReport
|
||||
from scripts.geojson_creator import process_geojson
|
||||
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.solar_angles import CitySolarAngles
|
||||
from scripts.pv_sizing_and_simulation import PVSizingSimulation
|
||||
from scripts.energy_system_retrofit_results import consumption_data, cost_data
|
||||
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
|
||||
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
|
||||
import hub.helpers.constants as cte
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from scripts.pv_feasibility import pv_feasibility
|
||||
|
||||
# Specify the GeoJSON file path
|
||||
input_files_path = (Path(__file__).parent / 'input_files')
|
||||
input_files_path.mkdir(parents=True, exist_ok=True)
|
||||
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
|
||||
geojson_file_path = input_files_path / 'output_buildings.geojson'
|
||||
output_path = (Path(__file__).parent / 'out_files').resolve()
|
||||
# Create city object from GeoJSON file
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
output_path.mkdir(parents=True, exist_ok=True)
|
||||
energy_plus_output_path = output_path / 'energy_plus_outputs'
|
||||
energy_plus_output_path.mkdir(parents=True, exist_ok=True)
|
||||
simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_results').resolve()
|
||||
simulation_results_path.mkdir(parents=True, exist_ok=True)
|
||||
sra_output_path = output_path / 'sra_outputs'
|
||||
sra_output_path.mkdir(parents=True, exist_ok=True)
|
||||
cost_analysis_output_path = output_path / 'cost_analysis'
|
||||
cost_analysis_output_path.mkdir(parents=True, exist_ok=True)
|
||||
city = GeometryFactory(file_type='geojson',
|
||||
path=geojson_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()
|
||||
ExportsFactory('sra', city, output_path).export()
|
||||
sra_path = (output_path / f'{city.name}_sra.xml').resolve()
|
||||
ExportsFactory('sra', city, sra_output_path).export()
|
||||
sra_path = (sra_output_path / f'{city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', city, output_path).enrich()
|
||||
energy_plus_workflow(city)
|
||||
ResultFactory('sra', city, sra_output_path).enrich()
|
||||
pv_feasibility(-73.5681295982132, 45.49218262677643, 0.0001, selected_buildings=city.buildings)
|
||||
energy_plus_workflow(city, energy_plus_output_path)
|
||||
solar_angles = CitySolarAngles(city.name,
|
||||
city.latitude,
|
||||
city.longitude,
|
||||
tilt_angle=45,
|
||||
surface_azimuth_angle=180).calculate
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_systems_percentage)
|
||||
EnergySystemsFactory('montreal_custom', city).enrich()
|
||||
SystemSizing(city.buildings).montreal_custom()
|
||||
current_system = new_system_results(city.buildings)
|
||||
current_status_energy_consumption = consumption_data(city)
|
||||
current_status_life_cycle_cost = {}
|
||||
for building in city.buildings:
|
||||
cost_retrofit_scenario = CURRENT_STATUS
|
||||
lcc_dataframe = Cost(building=building,
|
||||
retrofit_scenario=cost_retrofit_scenario,
|
||||
fuel_tariffs=['Electricity-D', 'Gas-Energir']).life_cycle
|
||||
lcc_dataframe.to_csv(cost_analysis_output_path / f'{building.name}_current_status_lcc.csv')
|
||||
current_status_life_cycle_cost[f'{building.name}'] = cost_data(building, lcc_dataframe, cost_retrofit_scenario)
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
|
||||
EnergySystemsFactory('montreal_future', city).enrich()
|
||||
for building in city.buildings:
|
||||
EnergySystemsSimulationFactory('archetype1', building=building, output_path=output_path).enrich()
|
||||
print(building.energy_consumption_breakdown[cte.ELECTRICITY][cte.COOLING] +
|
||||
building.energy_consumption_breakdown[cte.ELECTRICITY][cte.HEATING] +
|
||||
building.energy_consumption_breakdown[cte.ELECTRICITY][cte.DOMESTIC_HOT_WATER])
|
||||
new_system = new_system_results(city.buildings)
|
||||
# EnergySystemAnalysisReport(city, output_path).create_report(current_system, new_system)
|
||||
if 'PV' in building.energy_systems_archetype_name:
|
||||
ghi = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]]
|
||||
pv_sizing_simulation = PVSizingSimulation(building,
|
||||
solar_angles,
|
||||
tilt_angle=45,
|
||||
module_height=1,
|
||||
module_width=2,
|
||||
ghi=ghi)
|
||||
pv_sizing_simulation.pv_output()
|
||||
if building.energy_systems_archetype_name == 'PV+4Pipe+DHW':
|
||||
EnergySystemsSimulationFactory('archetype13', building=building, output_path=simulation_results_path).enrich()
|
||||
retrofitted_energy_consumption = consumption_data(city)
|
||||
retrofitted_life_cycle_cost = {}
|
||||
for building in city.buildings:
|
||||
costs = Cost(building=building, retrofit_scenario=SYSTEM_RETROFIT_AND_PV).life_cycle
|
||||
costs.to_csv(output_path / f'{building.name}_lcc.csv')
|
||||
(costs.loc['global_operational_costs', f'Scenario {SYSTEM_RETROFIT_AND_PV}'].
|
||||
to_csv(output_path / f'{building.name}_op.csv'))
|
||||
costs.loc['global_capital_costs', f'Scenario {SYSTEM_RETROFIT_AND_PV}'].to_csv(
|
||||
output_path / f'{building.name}_cc.csv')
|
||||
costs.loc['global_maintenance_costs', f'Scenario {SYSTEM_RETROFIT_AND_PV}'].to_csv(
|
||||
output_path / f'{building.name}_m.csv')
|
||||
cost_retrofit_scenario = SYSTEM_RETROFIT_AND_PV
|
||||
lcc_dataframe = Cost(building=building,
|
||||
retrofit_scenario=cost_retrofit_scenario,
|
||||
fuel_tariffs=['Electricity-D', 'Gas-Energir']).life_cycle
|
||||
lcc_dataframe.to_csv(cost_analysis_output_path / f'{building.name}_retrofitted_lcc.csv')
|
||||
retrofitted_life_cycle_cost[f'{building.name}'] = cost_data(building, lcc_dataframe, cost_retrofit_scenario)
|
||||
(EnergySystemRetrofitReport(city, output_path, 'PV Implementation and System Retrofit',
|
||||
current_status_energy_consumption, retrofitted_energy_consumption,
|
||||
current_status_life_cycle_cost, retrofitted_life_cycle_cost).create_report())
|
||||
|
||||
|
@ -187,7 +187,7 @@
|
||||
<hvac cost_unit="%">1.5</hvac>
|
||||
<photovoltaic cost_unit="%">3.6</photovoltaic>
|
||||
</subsidies>
|
||||
<electricity_export cost_unit="currency/kWh">0.07</electricity_export>
|
||||
<electricity_export cost_unit="currency/kWh">0.075</electricity_export>
|
||||
<tax_reduction cost_unit="%">5</tax_reduction>
|
||||
</incomes>
|
||||
</archetype>
|
||||
|
@ -1,71 +0,0 @@
|
||||
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_retrofit_report import EnergySystemRetrofitReport
|
||||
from scripts.geojson_creator import process_geojson
|
||||
from scripts import random_assignation
|
||||
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
||||
from scripts.energy_system_sizing import SystemSizing
|
||||
from scripts.solar_angles import CitySolarAngles
|
||||
from scripts.pv_sizing_and_simulation import PVSizingSimulation
|
||||
from scripts.energy_system_retrofit_results import consumption_data
|
||||
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
|
||||
from scripts.pv_feasibility import pv_feasibility
|
||||
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
|
||||
file_path = (Path(__file__).parent / 'input_files' / 'output_buildings.geojson')
|
||||
output_path = (Path(__file__).parent / 'out_files').resolve()
|
||||
simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_results').resolve()
|
||||
simulation_results_path.mkdir(parents=True, exist_ok=True)
|
||||
city = GeometryFactory(file_type='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
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
ExportsFactory('sra', city, output_path).export()
|
||||
sra_path = (output_path / f'{city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', city, output_path).enrich()
|
||||
pv_feasibility(-73.5681295982132, 45.49218262677643, 0.0001, selected_buildings=city.buildings)
|
||||
energy_plus_workflow(city)
|
||||
solar_angles = CitySolarAngles(city.name,
|
||||
city.latitude,
|
||||
city.longitude,
|
||||
tilt_angle=45,
|
||||
surface_azimuth_angle=180).calculate
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_systems_percentage)
|
||||
EnergySystemsFactory('montreal_custom', city).enrich()
|
||||
SystemSizing(city.buildings).montreal_custom()
|
||||
current_status_energy_consumption = consumption_data(city)
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
|
||||
EnergySystemsFactory('montreal_future', city).enrich()
|
||||
for building in city.buildings:
|
||||
if 'PV' in building.energy_systems_archetype_name:
|
||||
ghi = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]]
|
||||
pv_sizing_simulation = PVSizingSimulation(building,
|
||||
solar_angles,
|
||||
tilt_angle=45,
|
||||
module_height=1,
|
||||
module_width=2,
|
||||
ghi=ghi)
|
||||
pv_sizing_simulation.pv_output()
|
||||
if building.energy_systems_archetype_name == 'PV+4Pipe+DHW':
|
||||
EnergySystemsSimulationFactory('archetype13', building=building, output_path=simulation_results_path).enrich()
|
||||
retrofitted_energy_consumption = consumption_data(city)
|
||||
(EnergySystemRetrofitReport(city, output_path, 'PV Implementation and System Retrofit',
|
||||
current_status_energy_consumption, retrofitted_energy_consumption).create_report())
|
||||
|
@ -196,7 +196,7 @@ class TotalOperationalCosts(CostBase):
|
||||
if cooling is not None:
|
||||
hourly += cooling[i] / 3600
|
||||
if dhw is not None:
|
||||
dhw += dhw[i] / 3600
|
||||
hourly += dhw[i] / 3600
|
||||
hourly_fuel_consumption.append(hourly)
|
||||
else:
|
||||
heating = None
|
||||
|
@ -36,11 +36,10 @@ class TotalOperationalIncomes(CostBase):
|
||||
|
||||
for year in range(1, self._configuration.number_of_years + 1):
|
||||
price_increase_electricity = math.pow(1 + self._configuration.electricity_price_index, year)
|
||||
# todo: check the adequate assignation of price. Pilar
|
||||
price_export = archetype.income.electricity_export * cte.WATTS_HOUR_TO_JULES * 1000 # to account for unit change
|
||||
price_export = archetype.income.electricity_export # to account for unit change
|
||||
self._yearly_operational_incomes.loc[year, 'Incomes electricity'] = (
|
||||
onsite_electricity_production * price_export * price_increase_electricity
|
||||
(onsite_electricity_production / cte.WATTS_HOUR_TO_JULES) * price_export * price_increase_electricity
|
||||
)
|
||||
|
||||
self._yearly_operational_incomes.fillna(0, inplace=True)
|
||||
return self._yearly_operational_incomes
|
||||
return self._yearly_operational_incomes
|
@ -1,11 +1,8 @@
|
||||
import os
|
||||
import hub.helpers.constants as cte
|
||||
import matplotlib.pyplot as plt
|
||||
import random
|
||||
import matplotlib.colors as mcolors
|
||||
from matplotlib import cm
|
||||
from scripts.report_creation import LatexReport
|
||||
import matplotlib as mpl
|
||||
from matplotlib.ticker import MaxNLocator
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
@ -14,10 +11,12 @@ import glob
|
||||
|
||||
class EnergySystemRetrofitReport:
|
||||
def __init__(self, city, output_path, retrofit_scenario, current_status_energy_consumption_data,
|
||||
retrofitted_energy_consumption_data):
|
||||
retrofitted_energy_consumption_data, current_status_lcc_data, retrofitted_lcc_data):
|
||||
self.city = city
|
||||
self.current_status_data = current_status_energy_consumption_data
|
||||
self.retrofitted_data = retrofitted_energy_consumption_data
|
||||
self.current_status_lcc = current_status_lcc_data
|
||||
self.retrofitted_lcc = retrofitted_lcc_data
|
||||
self.output_path = output_path
|
||||
self.content = []
|
||||
self.retrofit_scenario = retrofit_scenario
|
||||
@ -334,7 +333,7 @@ class EnergySystemRetrofitReport:
|
||||
ax.spines['right'].set_linewidth(1.1)
|
||||
|
||||
# Plotting
|
||||
fig, axs = plt.subplots(3, 1, figsize=(20, 15), dpi=96)
|
||||
fig, axs = plt.subplots(3, 1, figsize=(20, 25), dpi=96)
|
||||
fig.suptitle(title, fontsize=16, weight='bold', alpha=.8)
|
||||
|
||||
plot_double_bar_chart(axs[0], 'heating', consumptions['Heating'][1], consumptions['Heating'][2],
|
||||
@ -356,11 +355,21 @@ class EnergySystemRetrofitReport:
|
||||
|
||||
return chart_path
|
||||
|
||||
|
||||
def yearly_consumption_comparison(self):
|
||||
current_total_consumption = self.current_status_data['total_consumption']
|
||||
retrofitted_total_consumption = self.retrofitted_data['total_consumption']
|
||||
|
||||
current_total_consumption = round(self.current_status_data['total_consumption'], 2)
|
||||
retrofitted_total_consumption = round(self.retrofitted_data['total_consumption'], 2)
|
||||
text = (
|
||||
f'The total yearly energy consumption before and after the retrofit are {current_total_consumption} MWh and '
|
||||
f'{retrofitted_total_consumption} MWh, respectively.')
|
||||
if retrofitted_total_consumption < current_total_consumption:
|
||||
change = str(round((current_total_consumption - retrofitted_total_consumption) * 100 / current_total_consumption,
|
||||
2))
|
||||
text += f'Therefore, the total yearly energy consumption decreased by {change} \%.'
|
||||
else:
|
||||
change = str(round((retrofitted_total_consumption - current_total_consumption) * 100 /
|
||||
retrofitted_total_consumption, 2))
|
||||
text += f'Therefore, the total yearly energy consumption increased by {change} \%. \par'
|
||||
self.report.add_text(text)
|
||||
|
||||
def pv_system(self):
|
||||
self.report.add_text('The first step in PV assessments is evaluating the potential of buildings for installing '
|
||||
@ -425,6 +434,85 @@ class EnergySystemRetrofitReport:
|
||||
|
||||
self.report.add_table(pv_output_table, caption='PV System Simulation Results', first_column_width=3)
|
||||
|
||||
def life_cycle_cost_stacked_bar(self, file_name, title):
|
||||
# Aggregate LCC components for current and retrofitted statuses
|
||||
current_status_capex = 0
|
||||
current_status_opex = 0
|
||||
current_status_maintenance = 0
|
||||
current_status_end_of_life = 0
|
||||
retrofitted_capex = 0
|
||||
retrofitted_opex = 0
|
||||
retrofitted_maintenance = 0
|
||||
retrofitted_end_of_life = 0
|
||||
|
||||
for building in self.city.buildings:
|
||||
current_status_capex += self.current_status_lcc[f'{building.name}']['capital_cost_per_sqm']
|
||||
retrofitted_capex += self.retrofitted_lcc[f'{building.name}']['capital_cost_per_sqm']
|
||||
current_status_opex += self.current_status_lcc[f'{building.name}']['operational_cost_per_sqm']
|
||||
retrofitted_opex += self.retrofitted_lcc[f'{building.name}']['operational_cost_per_sqm']
|
||||
current_status_maintenance += self.current_status_lcc[f'{building.name}']['maintenance_cost_per_sqm']
|
||||
retrofitted_maintenance += self.retrofitted_lcc[f'{building.name}']['maintenance_cost_per_sqm']
|
||||
current_status_end_of_life += self.current_status_lcc[f'{building.name}']['end_of_life_cost_per_sqm']
|
||||
retrofitted_end_of_life += self.retrofitted_lcc[f'{building.name}']['end_of_life_cost_per_sqm']
|
||||
|
||||
current_status_lcc_components_sqm = {
|
||||
'Capital Cost': current_status_capex / len(self.city.buildings),
|
||||
'Operational Cost': current_status_opex / len(self.city.buildings),
|
||||
'Maintenance Cost': current_status_maintenance / len(self.city.buildings),
|
||||
'End of Life Cost': current_status_end_of_life / len(self.city.buildings)
|
||||
}
|
||||
retrofitted_lcc_components_sqm = {
|
||||
'Capital Cost': retrofitted_capex / len(self.city.buildings),
|
||||
'Operational Cost': retrofitted_opex / len(self.city.buildings),
|
||||
'Maintenance Cost': retrofitted_maintenance / len(self.city.buildings),
|
||||
'End of Life Cost': retrofitted_end_of_life / len(self.city.buildings)
|
||||
}
|
||||
|
||||
labels = ['Current Status', 'Retrofitted Status']
|
||||
categories = ['Capital Cost', 'Operational Cost', 'Maintenance Cost', 'End of Life Cost']
|
||||
current_values = list(current_status_lcc_components_sqm.values())
|
||||
retrofitted_values = list(retrofitted_lcc_components_sqm.values())
|
||||
colors = ['#2196f3', '#ff5a5f', '#4caf50', '#ffc107']
|
||||
|
||||
# Data preparation
|
||||
bar_width = 0.35
|
||||
r = np.arange(len(labels))
|
||||
|
||||
fig, ax = plt.subplots(figsize=(12, 8), dpi=96)
|
||||
fig.suptitle(title, fontsize=16, weight='bold', alpha=.8)
|
||||
|
||||
# Plotting current status data
|
||||
bottom = np.zeros(2)
|
||||
for i, (category, color) in enumerate(zip(categories, colors)):
|
||||
values = [current_status_lcc_components_sqm[category], retrofitted_lcc_components_sqm[category]]
|
||||
ax.bar(r, values, bottom=bottom, color=color, edgecolor='white', width=bar_width, label=category)
|
||||
bottom += values
|
||||
|
||||
# Adding summation annotations at the top of the bars
|
||||
for idx, (x, total) in enumerate(zip(r, bottom)):
|
||||
ax.text(x, total, f'{total:.1f}', ha='center', va='bottom', fontsize=12, fontweight='bold')
|
||||
|
||||
# Adding labels, title, and grid
|
||||
ax.set_xlabel('LCC Components', fontsize=12, labelpad=10)
|
||||
ax.set_ylabel('Average Cost (CAD/m²)', fontsize=14, labelpad=10)
|
||||
ax.grid(which="major", axis='y', color='#DAD8D7', alpha=0.5, zorder=1)
|
||||
ax.set_xticks(r)
|
||||
ax.set_xticklabels(labels, rotation=45, ha='right')
|
||||
ax.legend()
|
||||
|
||||
# Adding a white background
|
||||
fig.patch.set_facecolor('white')
|
||||
|
||||
# Adjusting the margins around the plot area
|
||||
plt.subplots_adjust(left=0.05, right=0.95, top=0.9, bottom=0.2)
|
||||
|
||||
# Save the plot
|
||||
chart_path = self.charts_path / f'{file_name}.png'
|
||||
plt.savefig(chart_path, bbox_inches='tight')
|
||||
plt.close()
|
||||
|
||||
return chart_path
|
||||
|
||||
def create_report(self):
|
||||
# Add sections and text to the report
|
||||
self.report.add_section('Overview of the Current Status in Buildings')
|
||||
@ -448,6 +536,11 @@ class EnergySystemRetrofitReport:
|
||||
title='Monthly Energy Consumptions')
|
||||
current_consumption_breakdown_path = self.fuel_consumption_breakdown('City_Energy_Consumption_Breakdown',
|
||||
self.current_status_data)
|
||||
retrofitted_consumption_breakdown_path = self.fuel_consumption_breakdown(
|
||||
'fuel_consumption_breakdown_after_retrofit',
|
||||
self.retrofitted_data)
|
||||
life_cycle_cost_sqm_stacked_bar_chart_path = self.life_cycle_cost_stacked_bar('lcc_per_sqm',
|
||||
'LCC Analysis')
|
||||
# Add current state of energy demands in the city
|
||||
self.report.add_subsection('Current State of Energy Demands in the City')
|
||||
self.report.add_text('The total monthly energy demands in the city are shown in Figure 1. It should be noted '
|
||||
@ -487,6 +580,15 @@ class EnergySystemRetrofitReport:
|
||||
self.report.add_image(str(consumption_comparison).replace('\\', '/'),
|
||||
caption='Comparison of Total Monthly Energy Consumption in City Buildings',
|
||||
placement='H')
|
||||
self.yearly_consumption_comparison()
|
||||
self.report.add_text('Figure 7 shows the fuel consumption breakdown in the area after the retrofit.')
|
||||
self.report.add_image(str(retrofitted_consumption_breakdown_path).replace('\\', '/'),
|
||||
caption=f'Fuel Consumption Breakdown After {self.retrofit_scenario}',
|
||||
placement='H')
|
||||
self.report.add_subsection('Life Cycle Cost Analysis')
|
||||
self.report.add_image(str(life_cycle_cost_sqm_stacked_bar_chart_path).replace('\\', '/'),
|
||||
caption='Average Life Cycle Cost Components',
|
||||
placement='H')
|
||||
|
||||
# Save and compile the report
|
||||
self.report.save_report()
|
||||
|
@ -1,15 +1,88 @@
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
def hourly_electricity_consumption_profile(building):
|
||||
hourly_electricity_consumption = []
|
||||
energy_systems = building.energy_systems
|
||||
appliance = building.appliances_electrical_demand[cte.HOUR]
|
||||
lighting = building.lighting_electrical_demand[cte.HOUR]
|
||||
elec_heating = 0
|
||||
elec_cooling = 0
|
||||
elec_dhw = 0
|
||||
if cte.HEATING in building.energy_consumption_breakdown[cte.ELECTRICITY]:
|
||||
elec_heating = 1
|
||||
if cte.COOLING in building.energy_consumption_breakdown[cte.ELECTRICITY]:
|
||||
elec_cooling = 1
|
||||
if cte.DOMESTIC_HOT_WATER in 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 building.heating_consumption[cte.HOUR]]
|
||||
else:
|
||||
heating = 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 building.domestic_hot_water_consumption[cte.HOUR]]
|
||||
else:
|
||||
dhw = 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 building.cooling_consumption[cte.HOUR]]
|
||||
else:
|
||||
cooling = building.cooling_consumption[cte.HOUR]
|
||||
|
||||
for i in range(len(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:
|
||||
hourly += dhw[i] / 3600
|
||||
hourly_electricity_consumption.append(hourly)
|
||||
return hourly_electricity_consumption
|
||||
|
||||
|
||||
def consumption_data(city):
|
||||
current_status_energy_consumption_data = {}
|
||||
energy_consumption_data = {}
|
||||
for building in city.buildings:
|
||||
current_status_energy_consumption_data[f'{building.name}'] = {'heating_consumption': building.heating_consumption,
|
||||
'cooling_consumption': building.cooling_consumption,
|
||||
'domestic_hot_water_consumption':
|
||||
building.domestic_hot_water_consumption,
|
||||
'energy_consumption_breakdown':
|
||||
building.energy_consumption_breakdown}
|
||||
hourly_electricity_consumption = hourly_electricity_consumption_profile(building)
|
||||
energy_consumption_data[f'{building.name}'] = {'heating_consumption': building.heating_consumption,
|
||||
'cooling_consumption': building.cooling_consumption,
|
||||
'domestic_hot_water_consumption':
|
||||
building.domestic_hot_water_consumption,
|
||||
'energy_consumption_breakdown':
|
||||
building.energy_consumption_breakdown,
|
||||
'hourly_electricity_consumption': hourly_electricity_consumption}
|
||||
peak_electricity_consumption = 0
|
||||
for building in energy_consumption_data:
|
||||
peak_electricity_consumption += max(energy_consumption_data[building]['hourly_electricity_consumption'])
|
||||
heating_demand_monthly = []
|
||||
cooling_demand_monthly = []
|
||||
dhw_demand_monthly = []
|
||||
@ -54,14 +127,50 @@ def consumption_data(city):
|
||||
yearly_heating = 0
|
||||
yearly_cooling = 0
|
||||
yearly_dhw = 0
|
||||
yearly_appliance = 0
|
||||
yearly_lighting = 0
|
||||
for building in city.buildings:
|
||||
yearly_heating += building.heating_consumption[cte.YEAR][0] / 3.6e6
|
||||
yearly_cooling += building.cooling_consumption[cte.YEAR][0] / 3.6e6
|
||||
yearly_dhw += building.domestic_hot_water_consumption[cte.YEAR][0] / 3.6e6
|
||||
yearly_appliance += building.appliances_electrical_demand[cte.YEAR][0] / 3.6e9
|
||||
yearly_lighting += building.lighting_electrical_demand[cte.YEAR][0] / 3.6e9
|
||||
yearly_heating += building.heating_consumption[cte.YEAR][0] / 3.6e9
|
||||
yearly_cooling += building.cooling_consumption[cte.YEAR][0] / 3.6e9
|
||||
yearly_dhw += building.domestic_hot_water_consumption[cte.YEAR][0] / 3.6e9
|
||||
|
||||
total_consumption = yearly_heating + yearly_cooling + yearly_dhw
|
||||
current_status_energy_consumption_data['monthly_demands'] = monthly_demands
|
||||
current_status_energy_consumption_data['monthly_consumptions'] = monthly_consumptions
|
||||
current_status_energy_consumption_data['total_consumption'] = total_consumption
|
||||
total_consumption = yearly_heating + yearly_cooling + yearly_dhw + yearly_appliance + yearly_lighting
|
||||
energy_consumption_data['monthly_demands'] = monthly_demands
|
||||
energy_consumption_data['monthly_consumptions'] = monthly_consumptions
|
||||
energy_consumption_data['total_consumption'] = total_consumption
|
||||
energy_consumption_data['maximum_hourly_electricity_consumption'] = peak_electricity_consumption
|
||||
|
||||
return current_status_energy_consumption_data
|
||||
return energy_consumption_data
|
||||
|
||||
|
||||
def cost_data(building, lcc_dataframe, cost_retrofit_scenario):
|
||||
total_floor_area = 0
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
total_floor_area += thermal_zone.total_floor_area
|
||||
capital_cost = lcc_dataframe.loc['total_capital_costs_systems', f'Scenario {cost_retrofit_scenario}']
|
||||
operational_cost = lcc_dataframe.loc['total_operational_costs', f'Scenario {cost_retrofit_scenario}']
|
||||
maintenance_cost = lcc_dataframe.loc['total_maintenance_costs', f'Scenario {cost_retrofit_scenario}']
|
||||
end_of_life_cost = lcc_dataframe.loc['end_of_life_costs', f'Scenario {cost_retrofit_scenario}']
|
||||
operational_income = lcc_dataframe.loc['operational_incomes', f'Scenario {cost_retrofit_scenario}']
|
||||
total_life_cycle_cost = capital_cost + operational_cost + maintenance_cost + end_of_life_cost + operational_income
|
||||
specific_capital_cost = capital_cost / total_floor_area
|
||||
specific_operational_cost = operational_cost / total_floor_area
|
||||
specific_maintenance_cost = maintenance_cost / total_floor_area
|
||||
specific_end_of_life_cost = end_of_life_cost / total_floor_area
|
||||
specific_operational_income = operational_income / total_floor_area
|
||||
specific_life_cycle_cost = total_life_cycle_cost / total_floor_area
|
||||
life_cycle_cost_analysis = {'capital_cost': capital_cost,
|
||||
'capital_cost_per_sqm': specific_capital_cost,
|
||||
'operational_cost': operational_cost,
|
||||
'operational_cost_per_sqm': specific_operational_cost,
|
||||
'maintenance_cost': maintenance_cost,
|
||||
'maintenance_cost_per_sqm': specific_maintenance_cost,
|
||||
'end_of_life_cost': end_of_life_cost,
|
||||
'end_of_life_cost_per_sqm': specific_end_of_life_cost,
|
||||
'operational_income': operational_income,
|
||||
'operational_income_per_sqm': specific_operational_income,
|
||||
'total_life_cycle_cost': total_life_cycle_cost,
|
||||
'total_life_cycle_cost_per_sqm': specific_life_cycle_cost}
|
||||
return life_cycle_cost_analysis
|
||||
|
@ -9,10 +9,10 @@ from hub.imports.results_factory import ResultFactory
|
||||
sys.path.append('./')
|
||||
|
||||
|
||||
def energy_plus_workflow(city):
|
||||
def energy_plus_workflow(city, output_path):
|
||||
try:
|
||||
# city = city
|
||||
out_path = (Path(__file__).parent.parent / 'out_files')
|
||||
out_path = output_path
|
||||
files = glob.glob(f'{out_path}/*')
|
||||
|
||||
# for file in files:
|
||||
|
@ -9,10 +9,13 @@ from hub.exports.exports_factory import ExportsFactory
|
||||
|
||||
|
||||
def pv_feasibility(current_x, current_y, current_diff, selected_buildings):
|
||||
input_files_path = (Path(__file__).parent.parent / 'input_files')
|
||||
output_path = (Path(__file__).parent.parent / 'out_files').resolve()
|
||||
sra_output_path = output_path / 'sra_outputs' / 'extended_city_sra_outputs'
|
||||
sra_output_path.mkdir(parents=True, exist_ok=True)
|
||||
new_diff = current_diff * 5
|
||||
geojson_file = process_geojson(x=current_x, y=current_y, diff=new_diff, expansion=True)
|
||||
file_path = (Path(__file__).parent.parent / 'input_files' / 'output_buildings_expanded.geojson')
|
||||
output_path = (Path(__file__).parent.parent / 'out_files').resolve()
|
||||
file_path = input_files_path / 'output_buildings.geojson'
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='height',
|
||||
@ -20,10 +23,10 @@ def pv_feasibility(current_x, current_y, current_diff, selected_buildings):
|
||||
function_field='function',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
WeatherFactory('epw', city).enrich()
|
||||
ExportsFactory('sra', city, output_path).export()
|
||||
sra_path = (output_path / f'{city.name}_sra.xml').resolve()
|
||||
ExportsFactory('sra', city, sra_output_path).export()
|
||||
sra_path = (sra_output_path / f'{city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', city, output_path).enrich()
|
||||
ResultFactory('sra', city, sra_output_path).enrich()
|
||||
for selected_building in selected_buildings:
|
||||
for building in city.buildings:
|
||||
if selected_building.name == building.name:
|
||||
|
@ -377,8 +377,8 @@ class Archetype13:
|
||||
self._building.domestic_hot_water_consumption[cte.HOUR] = dhw_consumption
|
||||
self._building.domestic_hot_water_consumption[cte.MONTH] = (
|
||||
MonthlyValues.get_total_month(self._building.domestic_hot_water_consumption[cte.HOUR]))
|
||||
self._building.domestic_hot_water_consumption[cte.YEAR] = (
|
||||
sum(self._building.domestic_hot_water_consumption[cte.MONTH]))
|
||||
self._building.domestic_hot_water_consumption[cte.YEAR] = [
|
||||
sum(self._building.domestic_hot_water_consumption[cte.MONTH])]
|
||||
file_name = f'energy_system_simulation_results_{self._name}.csv'
|
||||
with open(self._output_path / file_name, 'w', newline='') as csvfile:
|
||||
output_file = csv.writer(csvfile)
|
||||
|
Loading…
Reference in New Issue
Block a user