Spaces:
Sleeping
Sleeping
Update data/drapery.py
Browse files- data/drapery.py +71 -14
data/drapery.py
CHANGED
@@ -888,6 +888,41 @@ class WindowHeatGainCalculator:
|
|
888 |
cltd_calculator: Instance of CLTDCalculator
|
889 |
"""
|
890 |
self.cltd_calculator = cltd_calculator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
891 |
|
892 |
def calculate_window_heat_gain(self, area: float, glazing_type: GlazingType,
|
893 |
frame_type: FrameType, orientation: str, hour: int,
|
@@ -906,6 +941,13 @@ class WindowHeatGainCalculator:
|
|
906 |
Returns:
|
907 |
Tuple of (conduction_heat_gain, solar_heat_gain) in Watts
|
908 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
909 |
# Get U-factor
|
910 |
u_factor = WINDOW_U_FACTORS.get((glazing_type, frame_type), 7.22)
|
911 |
|
@@ -919,13 +961,17 @@ class WindowHeatGainCalculator:
|
|
919 |
conduction_reduction = drapery.get_conduction_reduction() if drapery and drapery.enabled else 0.0
|
920 |
conduction_heat_gain = area * u_factor * cltd * (1.0 - conduction_reduction)
|
921 |
|
922 |
-
#
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
|
|
|
|
|
|
|
|
929 |
|
930 |
# Apply drapery shading coefficient
|
931 |
shading_coefficient = drapery.get_shading_coefficient(shgc) if drapery and drapery.enabled else 1.0
|
@@ -949,6 +995,13 @@ class WindowHeatGainCalculator:
|
|
949 |
Returns:
|
950 |
Tuple of (conduction_heat_gain, solar_heat_gain) in Watts
|
951 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
952 |
# Get U-factor
|
953 |
u_factor = SKYLIGHT_U_FACTORS.get((glazing_type, frame_type), 7.79)
|
954 |
|
@@ -962,13 +1015,17 @@ class WindowHeatGainCalculator:
|
|
962 |
conduction_reduction = drapery.get_conduction_reduction() if drapery and drapery.enabled else 0.0
|
963 |
conduction_heat_gain = area * u_factor * cltd * (1.0 - conduction_reduction)
|
964 |
|
965 |
-
#
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
|
|
|
|
|
|
|
|
972 |
|
973 |
# Apply drapery shading coefficient
|
974 |
shading_coefficient = drapery.get_shading_coefficient(shgc) if drapery and drapery.enabled else 1.0
|
|
|
888 |
cltd_calculator: Instance of CLTDCalculator
|
889 |
"""
|
890 |
self.cltd_calculator = cltd_calculator
|
891 |
+
|
892 |
+
def _validate_inputs(self, glazing_type: GlazingType, frame_type: FrameType, orientation: str, hour: int, latitude: Any, month: int) -> Tuple[bool, str, float]:
|
893 |
+
"""Validate inputs for window/skylight heat gain calculations, following ASHRAE."""
|
894 |
+
valid_orientations = ['North', 'Northeast', 'East', 'Southeast', 'South', 'Southwest', 'West', 'Northwest', 'Horizontal']
|
895 |
+
valid_latitudes = ['24N', '32N', '40N', '48N', '56N']
|
896 |
+
valid_months = list(range(1, 13))
|
897 |
+
valid_glazing_types = [e.value for e in GlazingType]
|
898 |
+
valid_frame_types = [e.value for e in FrameType]
|
899 |
+
|
900 |
+
if glazing_type.value not in valid_glazing_types:
|
901 |
+
return False, f"Invalid glazing type: {glazing_type.value}. Valid types: {valid_glazing_types}", 0.0
|
902 |
+
if frame_type.value not in valid_frame_types:
|
903 |
+
return False, f"Invalid frame type: {frame_type.value}. Valid types: {valid_frame_types}", 0.0
|
904 |
+
if orientation not in valid_orientations:
|
905 |
+
return False, f"Invalid orientation: {orientation}. Valid orientations: {valid_orientations}", 0.0
|
906 |
+
if hour not in range(24):
|
907 |
+
return False, "Hour must be between 0 and 23.", 0.0
|
908 |
+
if month not in valid_months:
|
909 |
+
return False, f"Invalid month: {month}. Valid months: 1-12", 0.0
|
910 |
+
|
911 |
+
# Handle latitude input
|
912 |
+
try:
|
913 |
+
if isinstance(latitude, str):
|
914 |
+
lat_str = latitude.upper().strip().replace('°', '').replace(' ', '')
|
915 |
+
num_part = ''.join(c for c in lat_str if c.isdigit() or c == '.')
|
916 |
+
lat_val = float(num_part)
|
917 |
+
if 'S' in lat_str:
|
918 |
+
lat_val = -lat_val
|
919 |
+
else:
|
920 |
+
lat_val = float(latitude)
|
921 |
+
abs_lat = abs(lat_val)
|
922 |
+
except (ValueError, TypeError):
|
923 |
+
return False, f"Invalid latitude: {latitude}. Use number (e.g., 40) or string (e.g., '40N')", 0.0
|
924 |
+
|
925 |
+
return True, "Valid inputs.", abs_lat
|
926 |
|
927 |
def calculate_window_heat_gain(self, area: float, glazing_type: GlazingType,
|
928 |
frame_type: FrameType, orientation: str, hour: int,
|
|
|
941 |
Returns:
|
942 |
Tuple of (conduction_heat_gain, solar_heat_gain) in Watts
|
943 |
"""
|
944 |
+
# Validate inputs
|
945 |
+
is_valid, error_msg, lat_val = self._validate_inputs(
|
946 |
+
glazing_type, frame_type, orientation, hour, self.cltd_calculator.latitude.value, self.cltd_calculator.month
|
947 |
+
)
|
948 |
+
if not is_valid:
|
949 |
+
raise ValueError(error_msg)
|
950 |
+
|
951 |
# Get U-factor
|
952 |
u_factor = WINDOW_U_FACTORS.get((glazing_type, frame_type), 7.22)
|
953 |
|
|
|
961 |
conduction_reduction = drapery.get_conduction_reduction() if drapery and drapery.enabled else 0.0
|
962 |
conduction_heat_gain = area * u_factor * cltd * (1.0 - conduction_reduction)
|
963 |
|
964 |
+
# Interpolate SCL for latitude
|
965 |
+
latitudes = [24, 32, 40, 48, 56]
|
966 |
+
lat1 = max([lat for lat in latitudes if lat <= lat_val], default=24)
|
967 |
+
lat2 = min([lat for lat in latitudes if lat >= lat_val], default=56)
|
968 |
+
scl1 = self.cltd_calculator.ashrae_tables.get_scl(f"{lat1}N", orientation, hour, self.cltd_calculator.month)
|
969 |
+
scl2 = self.cltd_calculator.ashrae_tables.get_scl(f"{lat2}N", orientation, hour, self.cltd_calculator.month)
|
970 |
+
if lat1 == lat2:
|
971 |
+
scl = scl1
|
972 |
+
else:
|
973 |
+
weight = (lat_val - lat1) / (lat2 - lat1)
|
974 |
+
scl = scl1 + weight * (scl2 - scl1)
|
975 |
|
976 |
# Apply drapery shading coefficient
|
977 |
shading_coefficient = drapery.get_shading_coefficient(shgc) if drapery and drapery.enabled else 1.0
|
|
|
995 |
Returns:
|
996 |
Tuple of (conduction_heat_gain, solar_heat_gain) in Watts
|
997 |
"""
|
998 |
+
# Validate inputs
|
999 |
+
is_valid, error_msg, lat_val = self._validate_inputs(
|
1000 |
+
glazing_type, frame_type, 'Horizontal', hour, self.cltd_calculator.latitude.value, self.cltd_calculator.month
|
1001 |
+
)
|
1002 |
+
if not is_valid:
|
1003 |
+
raise ValueError(error_msg)
|
1004 |
+
|
1005 |
# Get U-factor
|
1006 |
u_factor = SKYLIGHT_U_FACTORS.get((glazing_type, frame_type), 7.79)
|
1007 |
|
|
|
1015 |
conduction_reduction = drapery.get_conduction_reduction() if drapery and drapery.enabled else 0.0
|
1016 |
conduction_heat_gain = area * u_factor * cltd * (1.0 - conduction_reduction)
|
1017 |
|
1018 |
+
# Interpolate SCL for latitude
|
1019 |
+
latitudes = [24, 32, 40, 48, 56]
|
1020 |
+
lat1 = max([lat for lat in latitudes if lat <= lat_val], default=24)
|
1021 |
+
lat2 = min([lat for lat in latitudes if lat >= lat_val], default=56)
|
1022 |
+
scl1 = self.cltd_calculator.ashrae_tables.get_scl(f"{lat1}N", 'Horizontal', hour, self.cltd_calculator.month)
|
1023 |
+
scl2 = self.cltd_calculator.ashrae_tables.get_scl(f"{lat2}N", 'Horizontal', hour, self.cltd_calculator.month)
|
1024 |
+
if lat1 == lat2:
|
1025 |
+
scl = scl1
|
1026 |
+
else:
|
1027 |
+
weight = (lat_val - lat1) / (lat2 - lat1)
|
1028 |
+
scl = scl1 + weight * (scl2 - scl1)
|
1029 |
|
1030 |
# Apply drapery shading coefficient
|
1031 |
shading_coefficient = drapery.get_shading_coefficient(shgc) if drapery and drapery.enabled else 1.0
|