import numpy as np import pandas as pd import logging import math from tqdm import tqdm import pvlib from Utilities.Processes import ( calculate_no_of_panels, ) logger = logging.getLogger(__name__) def get_location(c): location = pvlib.location.Location( latitude=c["environment"]["location"]["latitude"], longitude=c["environment"]["location"]["longitude"], tz=c["simulation_date_time"]["tz"], ) return location def define_grid_layout(c): # get number of panels required no_of_panels = calculate_no_of_panels( c["array"]["system_size"], c["panel"]["peak_power"] ) # calculate pitch pitch = c["array"]["spacing"] + c["panel"]["dimensions"]["thickness"] # calculate minimum pitch if we don't want panel overlap at all min_pitch = c["panel"]["dimensions"]["length"] * math.cos( c["array"]["tilt"] / 180 * math.pi ) if pitch < min_pitch: logger.warning( f"Spacing is less than minimum pitch. Setting spacing to {min_pitch}." ) pitch = min_pitch logger.info(f"Pitch between panels: {pitch}m") # get maximum number of panels based on spacing and dimensions max__panels_per_row = np.floor( ( c["environment"]["roof"]["dimensions"]["width"] - (2 * c["array"]["edge_setback"] + c["panel"]["dimensions"]["width"]) ) / c["panel"]["dimensions"]["width"] ) max_number_of_rows = np.floor( ( c["environment"]["roof"]["dimensions"]["length"] - (2 * c["array"]["edge_setback"] + c["panel"]["dimensions"]["length"]) ) / pitch ) max_no_of_panels = max__panels_per_row * max_number_of_rows logger.info( f"Number of panels required: {no_of_panels}, Maximum panels possible: {max_no_of_panels}" ) if no_of_panels > max_no_of_panels: no_of_panels = max_no_of_panels logger.warning( f"Number of panels required exceeds maximum possible. Setting number of panels to {no_of_panels}." ) else: logger.info( f"Number of panels required is within the maximum possible. Setting number of panels to {no_of_panels}." ) # coordinate of panel determined by bottom left corner # x - row wise position, y - column wise position, z - height # first panel in row 1 is at (0, 0, 0) # nth panel in row 1 is at ((n-1)*panel_width, 0, 0) # first panel in nth row is at (0, (n-1)*(panel_thickness + spacing), 0) # create matrices for x, y, z coordinates of panels x = [] y = [] z = [] counter = 0 for j in range(int(max_number_of_rows)): for i in range(int(max__panels_per_row)): if counter < no_of_panels: x.append(i * c["panel"]["dimensions"]["width"]) y.append( j * pitch ) z.append(0) counter += 1 else: break coordinates = pd.DataFrame( { "x": x, "y": y, "z": z, } ) return coordinates, no_of_panels def get_solar_data(c): logger.info( f"Getting solar position data for {c['simulation_date_time']['start']} to {c['simulation_date_time']['end']}" ) """ Function to get solar position from PVLib """ location = get_location(c) times = pd.date_range( c["simulation_date_time"]["start"], c["simulation_date_time"]["end"], freq="15min", tz=location.tz, ) # Get solar position data using PVLib solar_positions = location.get_solarposition(times) clearsky_data = location.get_clearsky(times) return solar_positions, clearsky_data def calculate_shading(c, coordinates, solar_positions):