From 2f8f0ab9e9d662aebd4552072a6276c0de881059 Mon Sep 17 00:00:00 2001 From: Lucas Tan Date: Thu, 3 Apr 2025 19:47:16 +0800 Subject: [PATCH] sanity checking shading results --- README.md | 6 ++++++ Utilities/Optimisation.py | 1 + Utilities/Processes.py | 10 ++++++++++ Utilities/Shading.py | 11 ++++++----- config.yml | 13 ++++++++----- main.py | 15 +++++++++------ 6 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..b8b723f --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +Solar Calculations + +Solar Zenith: Angle between the position of the sun and vertical +Solar Azimuth: Horizontal angle with respect to north of the Sun's position + +Shadow Length Formula: Height of object / tan(solar_zenith) diff --git a/Utilities/Optimisation.py b/Utilities/Optimisation.py index bf6842b..279adcf 100644 --- a/Utilities/Optimisation.py +++ b/Utilities/Optimisation.py @@ -16,6 +16,7 @@ def optimise_vertical_panel_pitch(c): Returns: float: The negative of the energy production from vertical panels. """ + pitch += c["panel"]["dimensions"]["thickness"] c["array"]["spacing"] = pitch logging.info(f"Optimizing with pitch: {pitch}m") vertical_energy, _ = calculate_energy_production_vertical(c) diff --git a/Utilities/Processes.py b/Utilities/Processes.py index 80ce0c2..2499b5a 100644 --- a/Utilities/Processes.py +++ b/Utilities/Processes.py @@ -16,3 +16,13 @@ def calculate_no_of_panels(system_size, panel_peak_power): no_of_panels = np.ceil(system_size / panel_peak_power_kWp) return no_of_panels + + +def calculate_required_system_size(c): + c["array"]["system_size"] = ( + c["array"]["peak_power_demand"] + * c["array"]["DC_AC_ratio"] + * c["array"]["performance_ratio"] + ) + + return c diff --git a/Utilities/Shading.py b/Utilities/Shading.py index 2a2088d..aa27122 100644 --- a/Utilities/Shading.py +++ b/Utilities/Shading.py @@ -5,9 +5,7 @@ import math import pvlib -from Utilities.Processes import ( - calculate_no_of_panels, -) +from Utilities.Processes import calculate_no_of_panels, calculate_required_system_size logger = logging.getLogger(__name__) @@ -23,7 +21,6 @@ def get_location(c): def define_grid_layout(c, panel_tilt): - # get number of panels required no_of_panels = calculate_no_of_panels( c["array"]["system_size"], c["panel"]["peak_power"] ) @@ -52,7 +49,7 @@ def define_grid_layout(c, panel_tilt): max_number_of_rows = np.floor( ( c["environment"]["roof"]["dimensions"]["length"] - - (2 * c["array"]["edge_setback"] + c["panel"]["dimensions"]["length"]) + - (2 * c["array"]["edge_setback"]) ) / pitch ) @@ -129,6 +126,7 @@ def get_solar_data(c): def calculate_energy_production_vertical(c): + c = calculate_required_system_size(c) panel_coordinates, no_of_panels = define_grid_layout(c, panel_tilt=90) solar_positions, clearsky_data = get_solar_data(c) @@ -230,6 +228,9 @@ def calculate_energy_production_vertical(c): def calculate_energy_production_horizontal(c): + c["array"]["system_size"] = ( + c["array"]["system_size"] * c["array"]["horizontal_max_capacity"] + ) panel_coordinates, no_of_panels = define_grid_layout(c, panel_tilt=0) solar_positions, clearsky_data = get_solar_data(c) diff --git a/config.yml b/config.yml index ade5837..f03a19a 100644 --- a/config.yml +++ b/config.yml @@ -1,9 +1,12 @@ array: - system_size: 900 # in kWp - spacing: 21.8 # spacing between adjacent panel rows in m + peak_power_demand: 900 # in kWac + DC_AC_ratio: 1.2 # ratio of DC to AC power + spacing: 0.4 # spacing between adjacent panel rows in m edge_setback: 1.8 # distance from the edge of the roof to the array roof_slope: 0 slope: 0 # degrees from horizontal (+ve means shaded row is higher than the row in front) + horizontal_max_capacity: 0.75 # scale down due to peak power demand limit of NOVA + performance_ratio: 0.9 # ratio of actual energy output to the theoretical maximum simulation_date_time: start: 2025-03-30 00:00 # start date and time in ISO 8601 format @@ -13,9 +16,9 @@ environment: roof: dimensions: # dimensions all in m - length: 100 - width: 125 - albedo: 0.8 # % of light reflected from the surface + length: 50 + width: 40 + albedo: 0.2 # % of light reflected from the surface tilt: 0 # degrees from horizontal location: latitude: 3.1186108758412945 diff --git a/main.py b/main.py index 1309ab9..be83112 100644 --- a/main.py +++ b/main.py @@ -36,29 +36,32 @@ optimal_pitch, vertical_energy, no_of_panels_vertical = optimise_vertical_panel_ logger.info("Energy production for vertical panels calculated successfully.") logger.debug(f"Vertical Energy Production: {vertical_energy.sum()}") logger.debug("Number of panels: %d", no_of_panels_vertical) +logger.debug(f"System size: {no_of_panels_vertical * c['panel']['peak_power']/1e3} kWp") horizontal_energy, no_of_panels_horizontal = calculate_energy_production_horizontal(c) logger.info("Energy production for horizontal panels calculated successfully.") logger.debug(f"Horizontal Energy Production: {horizontal_energy.sum()}") logger.debug("Number of panels: %d", no_of_panels_horizontal) +logger.debug( + f"System size: {no_of_panels_horizontal * c['panel']['peak_power']/1e3} kWp" +) -NOVA_scaledown = 0.75 - -horizontal_energy_scaled = horizontal_energy * NOVA_scaledown logger.info("Energy production for horizontal panels scaled down to NOVA requirement.") logger.info( - f"Energy production for horizontal panels: {np.round(horizontal_energy_scaled.sum(),0)} kWh" + f"Energy production for horizontal panels: {np.round(horizontal_energy.sum(),0)} kWh" ) +logger.info(f"No. of panels for horizontal orientation: {int(no_of_panels_horizontal)}") logger.info( f"Energy production for vertical panels: {np.round(vertical_energy.sum(),0)} kWh" ) +logger.info(f"No. of panels for vertical orientation: {int(no_of_panels_vertical)}") # overlay horizontal and vertical energy production pl.figure(figsize=(10, 6)) pl.plot( - horizontal_energy_scaled.index, - horizontal_energy_scaled.values, + horizontal_energy.index, + horizontal_energy.values, label="Horizontal Panels", ) pl.plot(vertical_energy.index, vertical_energy.values, label="Vertical Panels")