code for creating panel geometries
This commit is contained in:
		
							parent
							
								
									1aa9bb60b3
								
							
						
					
					
						commit
						58e84a7998
					
				
							
								
								
									
										18
									
								
								Utilities/Processes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Utilities/Processes.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| import numpy as np | ||||
| 
 | ||||
| 
 | ||||
| def calculate_no_of_panels(system_size, panel_peak_power): | ||||
|     """ | ||||
|     Calculate the number of panels needed for a given system size and panel peak power. | ||||
| 
 | ||||
|     Args: | ||||
|         system_size (float): The total system size in kWp. | ||||
|         panel_peak_power (float): The peak power of a single panel in Wp. | ||||
| 
 | ||||
|     Returns: | ||||
|         int: The number of panels needed. | ||||
|     """ | ||||
|     panel_peak_power_kWp = panel_peak_power / 1000  # Convert Wp to kWp | ||||
|     no_of_panels = np.ceil(system_size / panel_peak_power_kWp) | ||||
| 
 | ||||
|     return no_of_panels | ||||
							
								
								
									
										113
									
								
								Utilities/Shading.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								Utilities/Shading.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | ||||
| import numpy as np | ||||
| import pandas as pd | ||||
| import logging | ||||
| 
 | ||||
| from ladybug_geometry.geometry3d.pointvector import Point3D, Vector3D | ||||
| from ladybug_geometry.geometry3d.plane import Plane | ||||
| from ladybug_geometry.geometry3d.polyface import Polyface3D | ||||
| 
 | ||||
| from Utilities.Processes import calculate_no_of_panels | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| 
 | ||||
| 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"] | ||||
|     ) | ||||
| 
 | ||||
|     # 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"] | ||||
|     ) | ||||
|     max_number_of_rows = np.floor( | ||||
|         ( | ||||
|             c["environment"]["roof"]["dimensions"]["length"] | ||||
|             - 2 * c["array"]["edge_setback"] | ||||
|         ) | ||||
|         / (c["array"]["spacing"] + c["panel"]["dimensions"]["thickness"]) | ||||
|     ) | ||||
|     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 * (c["panel"]["dimensions"]["thickness"] + c["array"]["spacing"]) | ||||
|                 ) | ||||
|                 z.append(0) | ||||
|                 counter += 1 | ||||
|             else: | ||||
|                 break | ||||
| 
 | ||||
|     coordinates = pd.DataFrame( | ||||
|         { | ||||
|             "x": x, | ||||
|             "y": y, | ||||
|             "z": z, | ||||
|         } | ||||
|     ) | ||||
|     return coordinates | ||||
| 
 | ||||
| 
 | ||||
| def create_panels(coordinates, c): | ||||
|     panel_width = c["panel"]["dimensions"]["width"] | ||||
|     panel_length = c["panel"]["dimensions"]["length"] | ||||
|     panel_thickness = c["panel"]["dimensions"]["thickness"] | ||||
| 
 | ||||
|     # For a vertical panel: | ||||
|     # - The vertical direction (panel height) is along the Z-axis. | ||||
|     y_axis = Vector3D(0, 0, 1)  # points upward | ||||
| 
 | ||||
|     # - The horizontal direction along the panel's width. | ||||
|     #   Here, we assume the width runs in the positive X-direction. | ||||
|     x_axis = Vector3D(1, 0, 0)  # points east | ||||
| 
 | ||||
|     panels = [] | ||||
|     for index, row in coordinates.iterrows(): | ||||
|         # Create the bottom-left corner of the panel | ||||
|         panel_origin = Point3D(row["x"], row["y"], row["z"]) | ||||
| 
 | ||||
|         # Create the plane for the panel | ||||
|         panel_plane = Plane(origin=panel_origin, y_axis=y_axis, x_axis=x_axis) | ||||
| 
 | ||||
|         # Create the panel geometry | ||||
|         panel = Polyface3D.from_box( | ||||
|             width=panel_width, | ||||
|             depth=panel_length, | ||||
|             height=panel_thickness, | ||||
|             base_plane=panel_plane, | ||||
|         ) | ||||
| 
 | ||||
|         panels.append(panel) | ||||
| 
 | ||||
|     return panels | ||||
							
								
								
									
										0
									
								
								Utilities/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								Utilities/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										26
									
								
								config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								config.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| array: | ||||
|   system_size: 500 # in kWp | ||||
|   spacing: 1 # spacing between adjacent panel rows in m | ||||
|   edge_setback: 1.8 # distance from the edge of the roof to the array | ||||
| 
 | ||||
| environment: | ||||
|   roof: | ||||
|     dimensions: | ||||
|       # dimensions all in m | ||||
|       length: 100 | ||||
|       width: 125 | ||||
|     albedo: 0.8 # % of light reflected from the surface | ||||
|     tilt: 0 # degrees from horizontal | ||||
| 
 | ||||
| location: | ||||
|   latitude: 3.1186108758412945 | ||||
|   longitude: 101.57639813680093 | ||||
| 
 | ||||
| panel: | ||||
|   peak_power: 710 # in Wp | ||||
|   bifaciality: 0.85 # rear face efficiency relative to front face | ||||
|   # dimensions all in m | ||||
|   dimensions: | ||||
|     length: 2.384 | ||||
|     width: 1.303 | ||||
|     thickness: 0.033 | ||||
							
								
								
									
										29
									
								
								main.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								main.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| # %% | ||||
| import yaml | ||||
| import logging | ||||
| from Utilities.Shading import define_grid_layout | ||||
| 
 | ||||
| logging.basicConfig( | ||||
|     level=logging.INFO, | ||||
|     format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", | ||||
|     datefmt="%Y-%m-%d %H:%M:%S", | ||||
| ) | ||||
| 
 | ||||
| stream_handler = logging.StreamHandler() | ||||
| stream_handler.setLevel(logging.INFO) | ||||
| stream_formatter = logging.Formatter("%(levelname)s: %(message)s") | ||||
| stream_handler.setFormatter(stream_formatter) | ||||
| logging.getLogger().addHandler(stream_handler) | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| config_path = "config.yml" | ||||
| 
 | ||||
| with open(config_path, "r") as file: | ||||
|     c = yaml.safe_load(file) | ||||
| logger.info("Configuration loaded successfully.") | ||||
| logger.debug(f"Configuration: {c}") | ||||
| 
 | ||||
| coordinates = define_grid_layout(c) | ||||
| 
 | ||||
| # %% | ||||
							
								
								
									
										44
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| asttokens==3.0.0 | ||||
| certifi==2025.1.31 | ||||
| charset-normalizer==3.4.1 | ||||
| colorama==0.4.6 | ||||
| comm==0.2.2 | ||||
| debugpy==1.8.13 | ||||
| decorator==5.2.1 | ||||
| executing==2.2.0 | ||||
| h5py==3.13.0 | ||||
| idna==3.10 | ||||
| ipykernel==6.29.5 | ||||
| ipython==9.0.2 | ||||
| ipython_pygments_lexers==1.1.1 | ||||
| jedi==0.19.2 | ||||
| jupyter_client==8.6.3 | ||||
| jupyter_core==5.7.2 | ||||
| ladybug-geometry==1.34.1 | ||||
| matplotlib-inline==0.1.7 | ||||
| nest-asyncio==1.6.0 | ||||
| nominatim==0.1 | ||||
| numpy==2.2.4 | ||||
| packaging==24.2 | ||||
| pandas==2.2.3 | ||||
| parso==0.8.4 | ||||
| platformdirs==4.3.7 | ||||
| prompt_toolkit==3.0.50 | ||||
| psutil==7.0.0 | ||||
| pure_eval==0.2.3 | ||||
| pvlib==0.12.0 | ||||
| Pygments==2.19.1 | ||||
| python-dateutil==2.9.0.post0 | ||||
| pytz==2025.2 | ||||
| pywin32==310 | ||||
| PyYAML==6.0.2 | ||||
| pyzmq==26.3.0 | ||||
| requests==2.32.3 | ||||
| scipy==1.15.2 | ||||
| six==1.17.0 | ||||
| stack-data==0.6.3 | ||||
| tornado==6.4.2 | ||||
| traitlets==5.14.3 | ||||
| tzdata==2025.2 | ||||
| urllib3==2.3.0 | ||||
| wcwidth==0.2.13 | ||||
							
								
								
									
										17
									
								
								test_sim.py
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								test_sim.py
									
									
									
									
									
								
							| @ -1,17 +0,0 @@ | ||||
| # %% | ||||
| import pvlib | ||||
| 
 | ||||
| from pvlib.modelchain import ModelChain | ||||
| from pvlib.pvsystem import PVSystem | ||||
| from pvlib.location import Location | ||||
| 
 | ||||
| # %% | ||||
| location = Location( | ||||
|     latitude=3.1114844514593343, longitude=101.5785743614895, tz="Asia/Kuala_Lumpur" | ||||
| ) | ||||
| system = PVSystem( | ||||
|     surface_tilt=90, | ||||
|     surface_azimuth=90, | ||||
| ) | ||||
| sandia_modules = pvlib.pvsystem.retrieve_sam("SandiaMod") | ||||
| cec_inverters = pvlib.pvsystem.retrieve_sam("CECInverter") | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user