From 96711ad41ef0d36a6b5cdadd4d67e817760f13c5 Mon Sep 17 00:00:00 2001 From: s_ranjbar Date: Mon, 22 Jul 2024 17:37:40 -0400 Subject: [PATCH] fix: small bug is cooling simulation and operational income are fixed --- .../cost/montreal_complete_cost_catalog.py | 2 +- scripts/costs/total_operational_incomes.py | 3 +- scripts/energy_system_retrofit_report.py | 21 +++--- scripts/energy_system_retrofit_results.py | 2 +- scripts/random_assignation.py | 8 +-- .../system_simulation_models/archetype13.py | 2 +- simulation_result_test.py | 67 +++++++++++++++++++ 7 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 simulation_result_test.py diff --git a/hub/catalog_factories/cost/montreal_complete_cost_catalog.py b/hub/catalog_factories/cost/montreal_complete_cost_catalog.py index 5e3927ee..0c51bfd2 100644 --- a/hub/catalog_factories/cost/montreal_complete_cost_catalog.py +++ b/hub/catalog_factories/cost/montreal_complete_cost_catalog.py @@ -48,7 +48,7 @@ class MontrealNewCatalog(Catalog): construction = float(archetype['incomes']['subsidies']['construction']['#text']) hvac = float(archetype['incomes']['subsidies']['hvac']['#text']) photovoltaic_system = float(archetype['incomes']['subsidies']['photovoltaic']['#text']) - electricity_exports = float(archetype['incomes']['electricity_export']['#text']) / 1000 / 3600 + electricity_exports = float(archetype['incomes']['electricity_export']['#text']) reduction_tax = float(archetype['incomes']['tax_reduction']['#text']) / 100 income = Income(construction_subsidy=construction, hvac_subsidy=hvac, diff --git a/scripts/costs/total_operational_incomes.py b/scripts/costs/total_operational_incomes.py index 66d789ed..f3a9f8ac 100644 --- a/scripts/costs/total_operational_incomes.py +++ b/scripts/costs/total_operational_incomes.py @@ -33,12 +33,11 @@ class TotalOperationalIncomes(CostBase): onsite_electricity_production = 0 else: onsite_electricity_production = building.onsite_electrical_production[cte.YEAR][0] - for year in range(1, self._configuration.number_of_years + 1): price_increase_electricity = math.pow(1 + self._configuration.electricity_price_index, year) price_export = archetype.income.electricity_export # to account for unit change self._yearly_operational_incomes.loc[year, 'Incomes electricity'] = ( - (onsite_electricity_production / cte.WATTS_HOUR_TO_JULES) * price_export * price_increase_electricity + (onsite_electricity_production / 3.6e6) * price_export * price_increase_electricity ) self._yearly_operational_incomes.fillna(0, inplace=True) diff --git a/scripts/energy_system_retrofit_report.py b/scripts/energy_system_retrofit_report.py index fcfb764f..738437c9 100644 --- a/scripts/energy_system_retrofit_report.py +++ b/scripts/energy_system_retrofit_report.py @@ -95,7 +95,6 @@ class EnergySystemRetrofitReport: ax.bar(months, values, color=color, width=0.6, zorder=2) ax.grid(which="major", axis='x', color='#DAD8D7', alpha=0.5, zorder=1) ax.grid(which="major", axis='y', color='#DAD8D7', alpha=0.5, zorder=1) - ax.set_xlabel('Month', fontsize=12, labelpad=10) ax.set_ylabel(ylabel, fontsize=14, labelpad=10) ax.set_title(title, fontsize=14, weight='bold', alpha=.8, pad=40) ax.xaxis.set_major_locator(MaxNLocator(integer=True)) @@ -444,6 +443,8 @@ class EnergySystemRetrofitReport: retrofitted_opex = 0 retrofitted_maintenance = 0 retrofitted_end_of_life = 0 + current_status_operational_income = 0 + retrofitted_operational_income = 0 for building in self.city.buildings: current_status_capex += self.current_status_lcc[f'{building.name}']['capital_cost_per_sqm'] @@ -454,25 +455,25 @@ class EnergySystemRetrofitReport: 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_operational_income += self.current_status_lcc[f'{building.name}']['operational_income_per_sqm'] + retrofitted_operational_income += self.retrofitted_lcc[f'{building.name}']['operational_income_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), + 'Operational Cost': (current_status_opex - current_status_operational_income) / 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) + '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), + 'Operational Cost': (retrofitted_opex - retrofitted_operational_income) / len(self.city.buildings), 'Maintenance Cost': retrofitted_maintenance / len(self.city.buildings), - 'End of Life Cost': retrofitted_end_of_life / 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'] + colors = ['#2196f3', '#ff5a5f', '#4caf50', '#ffc107'] # Added new color # Data preparation bar_width = 0.35 @@ -482,8 +483,8 @@ class EnergySystemRetrofitReport: 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)): + bottom = np.zeros(len(labels)) + for category, color in 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 diff --git a/scripts/energy_system_retrofit_results.py b/scripts/energy_system_retrofit_results.py index 9d85d0d9..1b84601a 100644 --- a/scripts/energy_system_retrofit_results.py +++ b/scripts/energy_system_retrofit_results.py @@ -104,7 +104,7 @@ def consumption_data(city): dhw_demand += building.domestic_hot_water_heat_demand[cte.MONTH][i] / 3.6e6 lighting_appliance_demand += building.lighting_electrical_demand[cte.MONTH][i] / 3.6e6 heating_consumption += building.heating_consumption[cte.MONTH][i] / 3.6e6 - if building.cooling_demand[cte.YEAR][0] == 0: + if building.cooling_consumption[cte.YEAR][0] == 0: cooling_consumption += building.cooling_demand[cte.MONTH][i] / (3.6e6 * 2) else: cooling_consumption += building.cooling_consumption[cte.MONTH][i] / 3.6e6 diff --git a/scripts/random_assignation.py b/scripts/random_assignation.py index ca7678bc..7483cced 100644 --- a/scripts/random_assignation.py +++ b/scripts/random_assignation.py @@ -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, diff --git a/scripts/system_simulation_models/archetype13.py b/scripts/system_simulation_models/archetype13.py index 77b52da6..aa9c03bd 100644 --- a/scripts/system_simulation_models/archetype13.py +++ b/scripts/system_simulation_models/archetype13.py @@ -190,7 +190,7 @@ class Archetype13: t_ret[0] = 13 for i in range(1, len(demand)): - if demand[i] > 0: + if demand[i] > 0.15 * self._cooling_peak_load: m[i] = hp.nominal_cooling_output / (cte.WATER_HEAT_CAPACITY * 5) if t_ret[i - 1] >= 13: if demand[i] < 0.25 * self._cooling_peak_load: diff --git a/simulation_result_test.py b/simulation_result_test.py new file mode 100644 index 00000000..a54477b4 --- /dev/null +++ b/simulation_result_test.py @@ -0,0 +1,67 @@ +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, 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, 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) +geojson_file_path = input_files_path / 'output_buildings.geojson' +output_path = (Path(__file__).parent / 'out_files').resolve() +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 +ConstructionFactory('nrcan', city).enrich() +UsageFactory('nrcan', city).enrich() +WeatherFactory('epw', city).enrich() +energy_plus_workflow(city, energy_plus_output_path) +random_assignation.call_random(city.buildings, random_assignation.residential_systems_percentage) +EnergySystemsFactory('montreal_custom', city).enrich() +SystemSizing(city.buildings).montreal_custom() +for i in range(12): + monthly_cooling = 0 + for building in city.buildings: + monthly_cooling += building.cooling_consumption[cte.MONTH][i] / (cte.WATTS_HOUR_TO_JULES * 1000) + print(monthly_cooling) +random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage) +EnergySystemsFactory('montreal_future', city).enrich() +for building in city.buildings: + if building.energy_systems_archetype_name == 'PV+4Pipe+DHW': + EnergySystemsSimulationFactory('archetype13', building=building, output_path=simulation_results_path).enrich() +for i in range(12): + monthly_cooling = 0 + for building in city.buildings: + monthly_cooling += building.cooling_consumption[cte.MONTH][i] / (cte.WATTS_HOUR_TO_JULES * 1000) + print(monthly_cooling) -- 2.39.2