Spaces:
Sleeping
Sleeping
Update utils/cooling_load.py
Browse files- utils/cooling_load.py +34 -38
utils/cooling_load.py
CHANGED
@@ -669,6 +669,21 @@ class CoolingLoadCalculator:
|
|
669 |
"""
|
670 |
Calculate cooling load for a window (conduction and solar).
|
671 |
Reference: ASHRAE Handbook—Fundamentals (2017), Chapter 18, Equations 18.12-18.13.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
672 |
"""
|
673 |
try:
|
674 |
# Validate inputs
|
@@ -685,24 +700,12 @@ class CoolingLoadCalculator:
|
|
685 |
if self.debug_mode:
|
686 |
logger.debug(f"Month converted: {month} -> {month_int}")
|
687 |
|
688 |
-
#
|
689 |
-
try:
|
690 |
-
lat_value = float(latitude.replace('N', ''))
|
691 |
-
if self.debug_mode:
|
692 |
-
logger.debug(f"Converted latitude {latitude} to {lat_value} for CLTDCalculator")
|
693 |
-
except ValueError:
|
694 |
-
if self.debug_mode:
|
695 |
-
logger.error(f"Invalid latitude format: {latitude}. Defaulting to 32.0")
|
696 |
-
lat_value = 32.0
|
697 |
-
|
698 |
-
# Initialize CLTDCalculator with numerical latitude
|
699 |
-
if self.debug_mode:
|
700 |
-
logger.debug(f"Initializing CLTDCalculator with lat_value={lat_value}")
|
701 |
cltd_calculator = CLTDCalculator(
|
702 |
indoor_temp=indoor_temp,
|
703 |
outdoor_max_temp=outdoor_temp,
|
704 |
outdoor_daily_range=11.7, # Default from drapery.py
|
705 |
-
latitude=
|
706 |
month=month_int
|
707 |
)
|
708 |
|
@@ -724,8 +727,6 @@ class CoolingLoadCalculator:
|
|
724 |
# Conduction load using CLTD
|
725 |
try:
|
726 |
glazing_key = glazing_type if glazing_type in ['Single Clear', 'Double Tinted', 'Low-E', 'Reflective'] else 'SingleClear'
|
727 |
-
if self.debug_mode:
|
728 |
-
logger.debug(f"Calling get_cltd_window with glazing_type={glazing_key}, orientation={window.orientation.value}, hour={hour}")
|
729 |
cltd = cltd_calculator.get_cltd_window(
|
730 |
glazing_type=glazing_key,
|
731 |
orientation=window.orientation.value,
|
@@ -757,22 +758,19 @@ class CoolingLoadCalculator:
|
|
757 |
|
758 |
# Solar load with latitude interpolation
|
759 |
try:
|
|
|
760 |
latitudes = [24, 32, 40, 48, 56]
|
761 |
lat1 = max([lat for lat in latitudes if lat <= lat_value], default=24)
|
762 |
lat2 = min([lat for lat in latitudes if lat >= lat_value], default=56)
|
763 |
-
lat1_str = f"{lat1}N"
|
764 |
-
lat2_str = f"{lat2}N"
|
765 |
|
766 |
-
if self.debug_mode:
|
767 |
-
logger.debug(f"Calling get_scl with lat1_str={lat1_str}, lat2_str={lat2_str}, orientation={window.orientation.value}, hour={hour}, month={month_int}")
|
768 |
scl1 = cltd_calculator.ashrae_tables.get_scl(
|
769 |
-
latitude=
|
770 |
orientation=window.orientation.value,
|
771 |
hour=hour,
|
772 |
month=month_int
|
773 |
)
|
774 |
scl2 = cltd_calculator.ashrae_tables.get_scl(
|
775 |
-
latitude=
|
776 |
orientation=window.orientation.value,
|
777 |
hour=hour,
|
778 |
month=month_int
|
@@ -849,14 +847,14 @@ class CoolingLoadCalculator:
|
|
849 |
hour = self.validate_hour(hour)
|
850 |
if self.debug_mode:
|
851 |
logger.debug(f"calculate_skylight_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation=Horizontal, glazing_type={glazing_type}, frame_type={frame_type}")
|
852 |
-
|
853 |
# Convert month string to integer for CLTDCalculator
|
854 |
month_map = {'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6,
|
855 |
'JUL': 7, 'AUG': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12}
|
856 |
month_int = month_map.get(month.upper(), 7) # Default to July
|
857 |
if self.debug_mode:
|
858 |
logger.debug(f"Month converted: {month} -> {month_int}")
|
859 |
-
|
860 |
# Initialize CLTDCalculator
|
861 |
cltd_calculator = CLTDCalculator(
|
862 |
indoor_temp=indoor_temp,
|
@@ -865,7 +863,7 @@ class CoolingLoadCalculator:
|
|
865 |
latitude=latitude,
|
866 |
month=month_int
|
867 |
)
|
868 |
-
|
869 |
# Determine U-factor and SHGC
|
870 |
u_value = skylight.u_value
|
871 |
shgc = skylight.shgc
|
@@ -880,7 +878,7 @@ class CoolingLoadCalculator:
|
|
880 |
except StopIteration:
|
881 |
if self.debug_mode:
|
882 |
logger.warning(f"Invalid glazing_type={glazing_type} or frame_type={frame_type}. Using default u_value={u_value}, shgc={shgc}")
|
883 |
-
|
884 |
# Conduction load using CLTD
|
885 |
try:
|
886 |
glazing_key = glazing_type if glazing_type in ['Single Clear', 'Double Tinted', 'Low-E', 'Reflective'] else 'SingleClear'
|
@@ -895,9 +893,9 @@ class CoolingLoadCalculator:
|
|
895 |
logger.error(f"get_cltd_skylight failed for glazing_type={glazing_key}: {str(e)}")
|
896 |
logger.warning("Using default CLTD=8.0°C")
|
897 |
cltd = 8.0
|
898 |
-
|
899 |
conduction_load = u_value * skylight.area * cltd
|
900 |
-
|
901 |
# Determine shading coefficient
|
902 |
effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
|
903 |
if adjusted_shgc is None and hasattr(skylight, 'drapery') and skylight.drapery and skylight.drapery.enabled:
|
@@ -911,29 +909,27 @@ class CoolingLoadCalculator:
|
|
911 |
else:
|
912 |
if self.debug_mode:
|
913 |
logger.debug(f"Using shading coefficient: {effective_shading_coefficient} (adjusted_shgc={adjusted_shgc}, drapery={'enabled' if hasattr(skylight, 'drapery') and skylight.drapery and skylight.drapery.enabled else 'disabled'})")
|
914 |
-
|
915 |
# Solar load with latitude interpolation
|
916 |
try:
|
917 |
lat_value = float(latitude.replace('N', ''))
|
918 |
latitudes = [24, 32, 40, 48, 56]
|
919 |
lat1 = max([lat for lat in latitudes if lat <= lat_value], default=24)
|
920 |
lat2 = min([lat for lat in latitudes if lat >= lat_value], default=56)
|
921 |
-
|
922 |
-
lat2_str = f"{lat2}N"
|
923 |
-
|
924 |
scl1 = cltd_calculator.ashrae_tables.get_scl(
|
925 |
-
latitude=
|
926 |
orientation='Horizontal',
|
927 |
hour=hour,
|
928 |
month=month_int
|
929 |
)
|
930 |
scl2 = cltd_calculator.ashrae_tables.get_scl(
|
931 |
-
latitude=
|
932 |
orientation='Horizontal',
|
933 |
hour=hour,
|
934 |
month=month_int
|
935 |
)
|
936 |
-
|
937 |
# Interpolate SCL
|
938 |
if lat1 == lat2:
|
939 |
scl = scl1
|
@@ -948,13 +944,13 @@ class CoolingLoadCalculator:
|
|
948 |
logger.error(f"get_scl failed for latitude={latitude}, month={month}, orientation=Horizontal: {str(e)}")
|
949 |
logger.warning("Using default SCL=100 W/m²")
|
950 |
scl = 100.0
|
951 |
-
|
952 |
solar_load = skylight.area * shgc * effective_shading_coefficient * scl
|
953 |
-
|
954 |
total_load = conduction_load + solar_load
|
955 |
if self.debug_mode:
|
956 |
logger.debug(f"Skylight load: conduction={conduction_load}, solar={solar_load}, total={total_load}, u_value={u_value}, shgc={shgc}, cltd={cltd}, effective_shading_coefficient={effective_shading_coefficient}")
|
957 |
-
|
958 |
return {
|
959 |
'conduction': max(conduction_load, 0.0),
|
960 |
'solar': max(solar_load, 0.0),
|
|
|
669 |
"""
|
670 |
Calculate cooling load for a window (conduction and solar).
|
671 |
Reference: ASHRAE Handbook—Fundamentals (2017), Chapter 18, Equations 18.12-18.13.
|
672 |
+
|
673 |
+
Args:
|
674 |
+
window: Window component
|
675 |
+
outdoor_temp: Outdoor temperature (°C)
|
676 |
+
indoor_temp: Indoor temperature (°C)
|
677 |
+
month: Design month (e.g., 'JUL')
|
678 |
+
hour: Hour of the day
|
679 |
+
latitude: Latitude (e.g., '40N')
|
680 |
+
shading_coefficient: Default shading coefficient
|
681 |
+
adjusted_shgc: Adjusted SHGC from external drapery calculation (optional)
|
682 |
+
glazing_type: Glazing type (e.g., 'Single Clear') (optional)
|
683 |
+
frame_type: Frame type (e.g., 'Aluminum without Thermal Break') (optional)
|
684 |
+
|
685 |
+
Returns:
|
686 |
+
Dictionary with conduction, solar, and total loads in Watts
|
687 |
"""
|
688 |
try:
|
689 |
# Validate inputs
|
|
|
700 |
if self.debug_mode:
|
701 |
logger.debug(f"Month converted: {month} -> {month_int}")
|
702 |
|
703 |
+
# Initialize CLTDCalculator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
704 |
cltd_calculator = CLTDCalculator(
|
705 |
indoor_temp=indoor_temp,
|
706 |
outdoor_max_temp=outdoor_temp,
|
707 |
outdoor_daily_range=11.7, # Default from drapery.py
|
708 |
+
latitude=latitude,
|
709 |
month=month_int
|
710 |
)
|
711 |
|
|
|
727 |
# Conduction load using CLTD
|
728 |
try:
|
729 |
glazing_key = glazing_type if glazing_type in ['Single Clear', 'Double Tinted', 'Low-E', 'Reflective'] else 'SingleClear'
|
|
|
|
|
730 |
cltd = cltd_calculator.get_cltd_window(
|
731 |
glazing_type=glazing_key,
|
732 |
orientation=window.orientation.value,
|
|
|
758 |
|
759 |
# Solar load with latitude interpolation
|
760 |
try:
|
761 |
+
lat_value = float(latitude.replace('N', ''))
|
762 |
latitudes = [24, 32, 40, 48, 56]
|
763 |
lat1 = max([lat for lat in latitudes if lat <= lat_value], default=24)
|
764 |
lat2 = min([lat for lat in latitudes if lat >= lat_value], default=56)
|
|
|
|
|
765 |
|
|
|
|
|
766 |
scl1 = cltd_calculator.ashrae_tables.get_scl(
|
767 |
+
latitude=float(lat1), # Use numerical latitude
|
768 |
orientation=window.orientation.value,
|
769 |
hour=hour,
|
770 |
month=month_int
|
771 |
)
|
772 |
scl2 = cltd_calculator.ashrae_tables.get_scl(
|
773 |
+
latitude=float(lat2), # Use numerical latitude
|
774 |
orientation=window.orientation.value,
|
775 |
hour=hour,
|
776 |
month=month_int
|
|
|
847 |
hour = self.validate_hour(hour)
|
848 |
if self.debug_mode:
|
849 |
logger.debug(f"calculate_skylight_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation=Horizontal, glazing_type={glazing_type}, frame_type={frame_type}")
|
850 |
+
|
851 |
# Convert month string to integer for CLTDCalculator
|
852 |
month_map = {'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6,
|
853 |
'JUL': 7, 'AUG': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12}
|
854 |
month_int = month_map.get(month.upper(), 7) # Default to July
|
855 |
if self.debug_mode:
|
856 |
logger.debug(f"Month converted: {month} -> {month_int}")
|
857 |
+
|
858 |
# Initialize CLTDCalculator
|
859 |
cltd_calculator = CLTDCalculator(
|
860 |
indoor_temp=indoor_temp,
|
|
|
863 |
latitude=latitude,
|
864 |
month=month_int
|
865 |
)
|
866 |
+
|
867 |
# Determine U-factor and SHGC
|
868 |
u_value = skylight.u_value
|
869 |
shgc = skylight.shgc
|
|
|
878 |
except StopIteration:
|
879 |
if self.debug_mode:
|
880 |
logger.warning(f"Invalid glazing_type={glazing_type} or frame_type={frame_type}. Using default u_value={u_value}, shgc={shgc}")
|
881 |
+
|
882 |
# Conduction load using CLTD
|
883 |
try:
|
884 |
glazing_key = glazing_type if glazing_type in ['Single Clear', 'Double Tinted', 'Low-E', 'Reflective'] else 'SingleClear'
|
|
|
893 |
logger.error(f"get_cltd_skylight failed for glazing_type={glazing_key}: {str(e)}")
|
894 |
logger.warning("Using default CLTD=8.0°C")
|
895 |
cltd = 8.0
|
896 |
+
|
897 |
conduction_load = u_value * skylight.area * cltd
|
898 |
+
|
899 |
# Determine shading coefficient
|
900 |
effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
|
901 |
if adjusted_shgc is None and hasattr(skylight, 'drapery') and skylight.drapery and skylight.drapery.enabled:
|
|
|
909 |
else:
|
910 |
if self.debug_mode:
|
911 |
logger.debug(f"Using shading coefficient: {effective_shading_coefficient} (adjusted_shgc={adjusted_shgc}, drapery={'enabled' if hasattr(skylight, 'drapery') and skylight.drapery and skylight.drapery.enabled else 'disabled'})")
|
912 |
+
|
913 |
# Solar load with latitude interpolation
|
914 |
try:
|
915 |
lat_value = float(latitude.replace('N', ''))
|
916 |
latitudes = [24, 32, 40, 48, 56]
|
917 |
lat1 = max([lat for lat in latitudes if lat <= lat_value], default=24)
|
918 |
lat2 = min([lat for lat in latitudes if lat >= lat_value], default=56)
|
919 |
+
|
|
|
|
|
920 |
scl1 = cltd_calculator.ashrae_tables.get_scl(
|
921 |
+
latitude=float(lat1), # Use numerical latitude
|
922 |
orientation='Horizontal',
|
923 |
hour=hour,
|
924 |
month=month_int
|
925 |
)
|
926 |
scl2 = cltd_calculator.ashrae_tables.get_scl(
|
927 |
+
latitude=float(lat2), # Use numerical latitude
|
928 |
orientation='Horizontal',
|
929 |
hour=hour,
|
930 |
month=month_int
|
931 |
)
|
932 |
+
|
933 |
# Interpolate SCL
|
934 |
if lat1 == lat2:
|
935 |
scl = scl1
|
|
|
944 |
logger.error(f"get_scl failed for latitude={latitude}, month={month}, orientation=Horizontal: {str(e)}")
|
945 |
logger.warning("Using default SCL=100 W/m²")
|
946 |
scl = 100.0
|
947 |
+
|
948 |
solar_load = skylight.area * shgc * effective_shading_coefficient * scl
|
949 |
+
|
950 |
total_load = conduction_load + solar_load
|
951 |
if self.debug_mode:
|
952 |
logger.debug(f"Skylight load: conduction={conduction_load}, solar={solar_load}, total={total_load}, u_value={u_value}, shgc={shgc}, cltd={cltd}, effective_shading_coefficient={effective_shading_coefficient}")
|
953 |
+
|
954 |
return {
|
955 |
'conduction': max(conduction_load, 0.0),
|
956 |
'solar': max(solar_load, 0.0),
|