feat: PV sizing module is added #7
|
@ -1,3 +1,4 @@
|
|||
import pandas as pd
|
||||
from scripts.geojson_creator import process_geojson
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
@ -8,11 +9,12 @@ from hub.imports.usage_factory import UsageFactory
|
|||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
from scripts.solar_angles import CitySolarAngles
|
||||
from scripts.radiation_tilted import RadiationTilted
|
||||
from scripts.ep_run_enrich import energy_plus_workflow
|
||||
import hub.helpers.constants as cte
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
from scripts.pv_sizing_and_simulation import PVSizingSimulation
|
||||
# Specify the GeoJSON file path
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0005)
|
||||
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()
|
||||
|
@ -32,8 +34,40 @@ 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()
|
||||
energy_plus_workflow(city)
|
||||
solar_angles = CitySolarAngles(city.name,
|
||||
city.latitude,
|
||||
city.longitude,
|
||||
tilt_angle=45,
|
||||
surface_azimuth_angle=180).calculate
|
||||
df = pd.DataFrame()
|
||||
df.index = ['yearly lighting (kWh)', 'yearly appliance (kWh)', 'yearly heating (kWh)', 'yearly cooling (kWh)',
|
||||
'yearly dhw (kWh)', 'roof area (m2)', 'used area for pv (m2)', 'number of panels', 'pv production (kWh)']
|
||||
for building in city.buildings:
|
||||
roof_horizontal = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]]
|
||||
solar_angles = (
|
||||
CitySolarAngles(city.name, city.latitude, city.longitude, tilt_angle=45, surface_azimuth_angle=180).calculate)
|
||||
RadiationTilted(building, solar_angles, tilt_angle=45, ghi=roof_horizontal).enrich()
|
||||
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()
|
||||
yearly_lighting = building.lighting_electrical_demand[cte.YEAR][0] / 1000
|
||||
yearly_appliance = building.appliances_electrical_demand[cte.YEAR][0] / 1000
|
||||
yearly_heating = building.heating_demand[cte.YEAR][0] / (3.6e6 * 3)
|
||||
yearly_cooling = building.cooling_demand[cte.YEAR][0] / (3.6e6 * 4.5)
|
||||
yearly_dhw = building.domestic_hot_water_heat_demand[cte.YEAR][0] / 1000
|
||||
roof_area = building.roofs[0].perimeter_area
|
||||
used_roof = pv_sizing_simulation.available_space()
|
||||
number_of_pv_panels = pv_sizing_simulation.total_number_of_panels
|
||||
yearly_pv = building.onsite_electrical_production[cte.YEAR][0] / 1000
|
||||
df[f'{building.name}'] = [yearly_lighting, yearly_appliance, yearly_heating, yearly_cooling, yearly_dhw, roof_area,
|
||||
used_roof, number_of_pv_panels, yearly_pv]
|
||||
|
||||
df.to_csv(output_path / 'pv.csv')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,21 +1,66 @@
|
|||
import math
|
||||
|
||||
from scripts.radiation_tilted import RadiationTilted
|
||||
from scripts.solar_angles import CitySolarAngles
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class PVSizingSimulation(RadiationTilted):
|
||||
def __init__(self, building, solar_angles, tilt_angle, module_height, module_width, ghi):
|
||||
super().__init__(building, solar_angles, tilt_angle, ghi)
|
||||
self.module_height = module_height
|
||||
self.module_width = module_width
|
||||
self.total_number_of_panels = 0
|
||||
self.enrich()
|
||||
|
||||
def available_space(self):
|
||||
roof_area = self.building.roofs[0].perimeter_area
|
||||
maintenance_factor = 0.1
|
||||
orientation_factor = 0.2
|
||||
if self.building.function == cte.RESIDENTIAL:
|
||||
mechanical_equipment_factor = 0.2
|
||||
else:
|
||||
mechanical_equipment_factor = 0.3
|
||||
available_roof = (maintenance_factor + orientation_factor + mechanical_equipment_factor) * roof_area
|
||||
return available_roof
|
||||
|
||||
def inter_row_spacing(self):
|
||||
winter_solstice = self.df[(self.df['AST'].dt.month == 12) &
|
||||
(self.df['AST'].dt.day == 21) &
|
||||
(self.df['AST'].dt.hour == 12)]
|
||||
solar_altitude = winter_solstice['solar altitude'].values[0]
|
||||
solar_azimuth = winter_solstice['solar azimuth'].values[0]
|
||||
distance = ((self.module_height * abs(math.cos(math.radians(solar_azimuth)))) /
|
||||
math.tan(math.radians(solar_altitude)))
|
||||
distance = float(format(distance, '.1f'))
|
||||
return distance
|
||||
|
||||
def number_of_panels(self, available_roof, inter_row_distance):
|
||||
space_dimension = math.sqrt(available_roof)
|
||||
space_dimension = float(format(space_dimension, '.2f'))
|
||||
panels_per_row = math.ceil(space_dimension / self.module_width)
|
||||
number_of_rows = math.ceil(space_dimension / inter_row_distance)
|
||||
self.total_number_of_panels = panels_per_row * number_of_rows
|
||||
return panels_per_row, number_of_rows
|
||||
|
||||
def pv_output(self):
|
||||
radiation = self.total_radiation_tilted
|
||||
pv_module_area = self.module_width * self.module_height
|
||||
available_roof = self.available_space()
|
||||
inter_row_spacing = self.inter_row_spacing()
|
||||
self.number_of_panels(available_roof, inter_row_spacing)
|
||||
system_efficiency = 0.2
|
||||
pv_hourly_production = [x * system_efficiency * self.total_number_of_panels * pv_module_area for x in radiation]
|
||||
self.building.onsite_electrical_production[cte.HOUR] = pv_hourly_production
|
||||
self.building.onsite_electrical_production[cte.MONTH] = (
|
||||
MonthlyValues.get_total_month(self.building.onsite_electrical_production[cte.HOUR]))
|
||||
self.building.onsite_electrical_production[cte.YEAR] = [sum(self.building.onsite_electrical_production[cte.MONTH])]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class PVSizingSimulation:
|
||||
def __init__(self, city, tilt_angle):
|
||||
self.city = city
|
||||
self.tilt_angle = tilt_angle
|
||||
self.solar_angles = CitySolarAngles(file_name=self.city.name,
|
||||
location_latitude=self.city.latitude,
|
||||
location_longitude=self.city.longitude,
|
||||
tilt_angle=self.tilt_angle,
|
||||
surface_azimuth_angle=180,
|
||||
standard_meridian=-75).calculate
|
||||
self.enrich_radiation_data()
|
||||
|
||||
def enrich_radiation_data(self):
|
||||
for building in self.city.buildings:
|
||||
roof_horizontal = [x / cte.WATTS_HOUR_TO_JULES for x in building.roofs[0].global_irradiance[cte.HOUR]]
|
||||
RadiationTilted(building, self.solar_angles, tilt_angle=self.tilt_angle, ghi=roof_horizontal).enrich()
|
||||
|
|
|
@ -13,9 +13,14 @@ class RadiationTilted:
|
|||
self.zeniths = solar_angles['zenith'].tolist()[:-1]
|
||||
self.incidents = solar_angles['incident angle'].tolist()[:-1]
|
||||
self.date_time = solar_angles['DateTime'].tolist()[:-1]
|
||||
data = {'DateTime': self.date_time, 'zenith': self.zeniths, 'incident angle': self.incidents, 'ghi': self.ghi}
|
||||
self.ast = solar_angles['AST'].tolist()[:-1]
|
||||
self.solar_azimuth = solar_angles['solar azimuth'].tolist()[:-1]
|
||||
self.solar_altitude = solar_angles['solar altitude'].tolist()[:-1]
|
||||
data = {'DateTime': self.date_time, 'AST': self.ast, 'solar altitude': self.solar_altitude, 'zenith': self.zeniths,
|
||||
'solar azimuth': self.solar_azimuth, 'incident angle': self.incidents, 'ghi': self.ghi}
|
||||
self.df = pd.DataFrame(data)
|
||||
self.df['DateTime'] = pd.to_datetime(self.df['DateTime'])
|
||||
self.df['AST'] = pd.to_datetime(self.df['AST'])
|
||||
self.df.set_index('DateTime', inplace=True)
|
||||
self.solar_constant = solar_constant
|
||||
self.maximum_clearness_index = maximum_clearness_index
|
||||
|
|
Loading…
Reference in New Issue
Block a user