mabuseif commited on
Commit
efc617f
·
verified ·
1 Parent(s): bb3de99

Upload solar_calculations.py

Browse files
Files changed (1) hide show
  1. data/solar_calculations.py +145 -0
data/solar_calculations.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from typing import List, Dict, Any
3
+ import math
4
+ from datetime import datetime
5
+ import streamlit as st
6
+
7
+ # Initialize session_state
8
+ if "climate_data" not in st.session_state:
9
+ st.session_state["climate_data"] = {
10
+ "latitude": 0.0,
11
+ "longitude": 0.0,
12
+ "timezone": 0.0
13
+ }
14
+
15
+ class SolarCalculations:
16
+ """Class for performing solar radiation and angle calculations based on ASHRAE methodologies."""
17
+
18
+ @staticmethod
19
+ def day_of_year(month: int, day: int, year: int) -> int:
20
+ """Calculate day of the year (n) from month, day, and year, accounting for leap years."""
21
+ days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
22
+ if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0):
23
+ days_in_month[1] = 29
24
+ return sum(days_in_month[:month-1]) + day
25
+
26
+ @staticmethod
27
+ def equation_of_time(n: int) -> float:
28
+ """Calculate Equation of Time (EOT) in minutes using Spencer's formula."""
29
+ B = (n - 1) * 360 / 365
30
+ B_rad = math.radians(B)
31
+ EOT = 229.2 * (0.000075 + 0.001868 * math.cos(B_rad) - 0.032077 * math.sin(B_rad) -
32
+ 0.014615 * math.cos(2 * B_rad) - 0.04089 * math.sin(2 * B_rad))
33
+ return EOT
34
+
35
+ @staticmethod
36
+ def calculate_solar_parameters(
37
+ hourly_data: List[Dict[str, Any]],
38
+ latitude: float,
39
+ longitude: float,
40
+ timezone: float,
41
+ ground_reflectivity: float,
42
+ surface_tilt: float,
43
+ year: int = 2025
44
+ ) -> List[Dict[str, Any]]:
45
+ """Calculate solar angles and ground-reflected radiation for hourly data with GHI > 0."""
46
+ # Display input parameters in Streamlit UI
47
+ st.write("### Input Parameters")
48
+ st.write(f"- **Latitude**: {latitude}°")
49
+ st.write(f"- **Longitude**: {longitude}°")
50
+ st.write(f"- **Timezone**: {timezone} hours")
51
+ st.write(f"- **Ground Reflectivity**: {ground_reflectivity}")
52
+ st.write(f"- **Surface Tilt**: {surface_tilt}°")
53
+ st.write(f"- **Year**: {year}")
54
+ st.write("") # Add spacing
55
+
56
+ results = []
57
+ lambda_std = 15 * timezone # Standard meridian longitude (°)
58
+ first_hour = True
59
+
60
+ for record in hourly_data:
61
+ if record["global_horizontal_radiation"] <= 0:
62
+ continue # Skip hours with no solar radiation
63
+
64
+ # Step 1: Extract data
65
+ month = record["month"]
66
+ day = record["day"]
67
+ hour = record["hour"]
68
+ ghi = record["global_horizontal_radiation"]
69
+ dni = record["direct_normal_radiation"]
70
+ dhi = record["diffuse_horizontal_radiation"]
71
+
72
+ if first_hour:
73
+ st.write(f"### Calculations for First Hour (Month: {month}, Day: {day}, Hour: {hour})")
74
+ st.write(f"- **Global Horizontal Radiation (GHI)**: {ghi} W/m²")
75
+ st.write(f"- **Direct Normal Radiation (DNI)**: {dni} W/m²")
76
+ st.write(f"- **Diffuse Horizontal Radiation (DHI)**: {dhi} W/m²")
77
+
78
+ # Step 2: Local Solar Time (LST) with Equation of Time
79
+ n = SolarCalculations.day_of_year(month, day, year)
80
+ if first_hour:
81
+ st.write(f"- **Day of Year (n)**: {n}")
82
+
83
+ EOT = SolarCalculations.equation_of_time(n)
84
+ if first_hour:
85
+ st.write(f"- **Equation of Time (EOT)**: {EOT:.2f} minutes")
86
+
87
+ standard_time = hour - 1 + 0.5 # Convert to decimal, assume mid-hour
88
+ LST = standard_time + (4 * (lambda_std - longitude) + EOT)/60
89
+ if first_hour:
90
+ st.write(f"- **Local Solar Time (LST)**: {LST:.2f} hours")
91
+
92
+ # Step 3: Solar Declination (δ)
93
+ delta = 23.45 * math.sin(math.radians(360 / 365 * (284 + n)))
94
+ if first_hour:
95
+ st.write(f"- **Solar Declination (δ)**: {delta:.2f}°")
96
+
97
+ # Step 4: Hour Angle (HRA)
98
+ hra = 15 * (LST - 12)
99
+ if first_hour:
100
+ st.write(f"- **Hour Angle (HRA)**: {hra:.2f}°")
101
+
102
+ # Step 5: Solar Altitude (α) and Azimuth (Az)
103
+ phi = math.radians(latitude)
104
+ delta_rad = math.radians(delta)
105
+ hra_rad = math.radians(hra)
106
+
107
+ sin_alpha = math.sin(phi) * math.sin(delta_rad) + math.cos(phi) * math.cos(delta_rad) * math.cos(hra_rad)
108
+ alpha = math.degrees(math.asin(sin_alpha))
109
+ if first_hour:
110
+ st.write(f"- **Solar Altitude (α)**: {alpha:.2f}°")
111
+
112
+ if abs(math.cos(math.radians(alpha))) < 0.01:
113
+ azimuth = 0 # North at sunrise/sunset
114
+ else:
115
+ sin_az = math.cos(delta_rad) * math.sin(hra_rad) / math.cos(math.radians(alpha))
116
+ cos_az = (sin_alpha * math.sin(phi) - math.sin(delta_rad)) / (math.cos(math.radians(alpha)) * math.cos(phi))
117
+ azimuth = math.degrees(math.atan2(sin_az, cos_az))
118
+ if hra > 0: # Afternoon
119
+ azimuth = 360 - azimuth if azimuth > 0 else -azimuth
120
+ if first_hour:
121
+ st.write(f"- **Solar Azimuth (Az)**: {azimuth:.2f}°")
122
+
123
+ # Step 6: Ground-Reflected Radiation (I_gr)
124
+ view_factor = (1 - math.cos(math.radians(surface_tilt))) / 2
125
+ ground_reflected = ground_reflectivity * ghi * view_factor
126
+ if first_hour:
127
+ st.write(f"- **Ground-Reflected Radiation (I_gr)**: {ground_reflected:.2f} W/m²")
128
+ st.write("") # Add spacing
129
+ first_hour = False
130
+
131
+ # Store results
132
+ result = {
133
+ "month": month,
134
+ "day": day,
135
+ "hour": hour,
136
+ "declination": round(delta, 2),
137
+ "LST": round(LST, 2),
138
+ "HRA": round(hra, 2),
139
+ "altitude": round(alpha, 2),
140
+ "azimuth": round(azimuth, 2),
141
+ "ground_reflected": round(ground_reflected, 2)
142
+ }
143
+ results.append(result)
144
+
145
+ return results