From c40900bd30e004edbe6484d6cebe74373fa39e96 Mon Sep 17 00:00:00 2001 From: Majid Rezaei Date: Sun, 23 Jun 2024 18:27:31 -0400 Subject: [PATCH] feature: add simultinity factor calculations --- main.py | 31 +++++++++ .../simultinity_factor.py | 64 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 scripts/district_heating_network/simultinity_factor.py diff --git a/main.py b/main.py index e69de29b..f4692200 100644 --- a/main.py +++ b/main.py @@ -0,0 +1,31 @@ +from pathlib import Path +from scripts.district_heating_network.simultinity_factor import DemandShiftProcessor +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 +import hub.helpers.constants as cte + +file_path = (Path(__file__).parent / 'input_files' / 'output_buildings.geojson') + +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) + +processor = DemandShiftProcessor(city) +processor.process_demands() diff --git a/scripts/district_heating_network/simultinity_factor.py b/scripts/district_heating_network/simultinity_factor.py new file mode 100644 index 00000000..e9e4d470 --- /dev/null +++ b/scripts/district_heating_network/simultinity_factor.py @@ -0,0 +1,64 @@ +import pandas as pd +import numpy as np + + +class DemandShiftProcessor: + def __init__(self, city): + self.city = city + + def random_shift(self, series): + shift_amount = np.random.randint(0, 2) + return series.shift(shift_amount).fillna(series.shift(shift_amount - len(series))) + + def process_demands(self): + building_dfs = [] + + for building in self.city.buildings: + df = self.convert_building_to_dataframe(building) + df.set_index('Date/Time', inplace=True) + shifted_demands = df.apply(self.random_shift, axis=0) + self.update_building_demands(building, shifted_demands) + building_dfs.append(shifted_demands) + + combined_df = pd.concat(building_dfs, axis=1) + self.calculate_and_set_simultaneity_factor(combined_df) + + def convert_building_to_dataframe(self, building): + data = { + "Date/Time": self.generate_date_time_index(), + "Heating_Demand": building.heating_demand["hour"], + "Cooling_Demand": building.cooling_demand["hour"] + } + return pd.DataFrame(data) + + def generate_date_time_index(self): + # Generate hourly date time index for a full year in 2013 + date_range = pd.date_range(start="2013-01-01 00:00:00", end="2013-12-31 23:00:00", freq='H') + return date_range.strftime('%m/%d %H:%M:%S').tolist() + + def update_building_demands(self, building, shifted_demands): + heating_shifted = shifted_demands["Heating_Demand"] + cooling_shifted = shifted_demands["Cooling_Demand"] + + building.heating_demand = self.calculate_new_demands(heating_shifted) + building.cooling_demand = self.calculate_new_demands(cooling_shifted) + + def calculate_new_demands(self, shifted_series): + new_demand = { + "hour": shifted_series.tolist(), + "month": self.calculate_monthly_demand(shifted_series), + "year": [shifted_series.sum()] + } + return new_demand + + def calculate_monthly_demand(self, series): + series.index = pd.to_datetime(series.index, format='%m/%d %H:%M:%S') + monthly_demand = series.resample('M').sum() + return monthly_demand.tolist() + + def calculate_and_set_simultaneity_factor(self, combined_df): + total_demand_original = combined_df.sum(axis=1) + peak_total_demand_original = total_demand_original.max() + individual_peak_demands = combined_df.max(axis=0) + sum_individual_peak_demands = individual_peak_demands.sum() + self.city.simultaneity_factor = peak_total_demand_original / sum_individual_peak_demands