Spaces:
Sleeping
Sleeping
Update utils/cooling_load.py
Browse files- utils/cooling_load.py +43 -29
utils/cooling_load.py
CHANGED
@@ -669,21 +669,6 @@ 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 |
-
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
|
@@ -692,16 +677,35 @@ class CoolingLoadCalculator:
|
|
692 |
hour = self.validate_hour(hour)
|
693 |
if self.debug_mode:
|
694 |
logger.debug(f"calculate_window_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation={window.orientation.value}, glazing_type={glazing_type}, frame_type={frame_type}")
|
695 |
-
|
696 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
697 |
cltd_calculator = CLTDCalculator(
|
698 |
indoor_temp=indoor_temp,
|
699 |
outdoor_max_temp=outdoor_temp,
|
700 |
outdoor_daily_range=11.7, # Default from drapery.py
|
701 |
-
latitude=latitude
|
702 |
month=month_int
|
703 |
)
|
704 |
-
|
705 |
# Determine U-factor and SHGC
|
706 |
u_value = window.u_value
|
707 |
shgc = window.shgc
|
@@ -716,10 +720,12 @@ class CoolingLoadCalculator:
|
|
716 |
except StopIteration:
|
717 |
if self.debug_mode:
|
718 |
logger.warning(f"Invalid glazing_type={glazing_type} or frame_type={frame_type}. Using default u_value={u_value}, shgc={shgc}")
|
719 |
-
|
720 |
# Conduction load using CLTD
|
721 |
try:
|
722 |
glazing_key = glazing_type if glazing_type in ['Single Clear', 'Double Tinted', 'Low-E', 'Reflective'] else 'SingleClear'
|
|
|
|
|
723 |
cltd = cltd_calculator.get_cltd_window(
|
724 |
glazing_type=glazing_key,
|
725 |
orientation=window.orientation.value,
|
@@ -732,9 +738,9 @@ class CoolingLoadCalculator:
|
|
732 |
logger.error(f"get_cltd_window failed for glazing_type={glazing_key}: {str(e)}")
|
733 |
logger.warning("Using default CLTD=8.0°C")
|
734 |
cltd = 8.0
|
735 |
-
|
736 |
conduction_load = u_value * window.area * cltd
|
737 |
-
|
738 |
# Determine shading coefficient
|
739 |
effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
|
740 |
if adjusted_shgc is None and hasattr(window, 'drapery') and window.drapery and window.drapery.enabled:
|
@@ -748,16 +754,17 @@ class CoolingLoadCalculator:
|
|
748 |
else:
|
749 |
if self.debug_mode:
|
750 |
logger.debug(f"Using shading coefficient: {effective_shading_coefficient} (adjusted_shgc={adjusted_shgc}, drapery={'enabled' if hasattr(window, 'drapery') and window.drapery and window.drapery.enabled else 'disabled'})")
|
751 |
-
|
752 |
# Solar load with latitude interpolation
|
753 |
try:
|
754 |
-
lat_value = float(latitude.replace('N', ''))
|
755 |
latitudes = [24, 32, 40, 48, 56]
|
756 |
lat1 = max([lat for lat in latitudes if lat <= lat_value], default=24)
|
757 |
lat2 = min([lat for lat in latitudes if lat >= lat_value], default=56)
|
758 |
lat1_str = f"{lat1}N"
|
759 |
lat2_str = f"{lat2}N"
|
760 |
-
|
|
|
|
|
761 |
scl1 = cltd_calculator.ashrae_tables.get_scl(
|
762 |
latitude=lat1_str,
|
763 |
orientation=window.orientation.value,
|
@@ -770,7 +777,7 @@ class CoolingLoadCalculator:
|
|
770 |
hour=hour,
|
771 |
month=month_int
|
772 |
)
|
773 |
-
|
774 |
# Interpolate SCL
|
775 |
if lat1 == lat2:
|
776 |
scl = scl1
|
@@ -785,13 +792,13 @@ class CoolingLoadCalculator:
|
|
785 |
logger.error(f"get_scl failed for latitude={latitude}, month={month}, orientation={window.orientation.value}: {str(e)}")
|
786 |
logger.warning("Using default SCL=100 W/m²")
|
787 |
scl = 100.0
|
788 |
-
|
789 |
solar_load = window.area * shgc * effective_shading_coefficient * scl
|
790 |
-
|
791 |
total_load = conduction_load + solar_load
|
792 |
if self.debug_mode:
|
793 |
logger.debug(f"Window load: conduction={conduction_load}, solar={solar_load}, total={total_load}, u_value={u_value}, shgc={shgc}, cltd={cltd}, effective_shading_coefficient={effective_shading_coefficient}")
|
794 |
-
|
795 |
return {
|
796 |
'conduction': max(conduction_load, 0.0),
|
797 |
'solar': max(solar_load, 0.0),
|
@@ -843,6 +850,13 @@ class CoolingLoadCalculator:
|
|
843 |
if self.debug_mode:
|
844 |
logger.debug(f"calculate_skylight_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation=Horizontal, glazing_type={glazing_type}, frame_type={frame_type}")
|
845 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
846 |
# Initialize CLTDCalculator
|
847 |
cltd_calculator = CLTDCalculator(
|
848 |
indoor_temp=indoor_temp,
|
|
|
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
|
|
|
677 |
hour = self.validate_hour(hour)
|
678 |
if self.debug_mode:
|
679 |
logger.debug(f"calculate_window_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation={window.orientation.value}, glazing_type={glazing_type}, frame_type={frame_type}")
|
680 |
+
|
681 |
+
# Convert month string to integer for CLTDCalculator
|
682 |
+
month_map = {'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6,
|
683 |
+
'JUL': 7, 'AUG': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12}
|
684 |
+
month_int = month_map.get(month.upper(), 7) # Default to July
|
685 |
+
if self.debug_mode:
|
686 |
+
logger.debug(f"Month converted: {month} -> {month_int}")
|
687 |
+
|
688 |
+
# Convert latitude to numerical value
|
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=lat_value, # Pass numerical latitude
|
706 |
month=month_int
|
707 |
)
|
708 |
+
|
709 |
# Determine U-factor and SHGC
|
710 |
u_value = window.u_value
|
711 |
shgc = window.shgc
|
|
|
720 |
except StopIteration:
|
721 |
if self.debug_mode:
|
722 |
logger.warning(f"Invalid glazing_type={glazing_type} or frame_type={frame_type}. Using default u_value={u_value}, shgc={shgc}")
|
723 |
+
|
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,
|
|
|
738 |
logger.error(f"get_cltd_window failed for glazing_type={glazing_key}: {str(e)}")
|
739 |
logger.warning("Using default CLTD=8.0°C")
|
740 |
cltd = 8.0
|
741 |
+
|
742 |
conduction_load = u_value * window.area * cltd
|
743 |
+
|
744 |
# Determine shading coefficient
|
745 |
effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
|
746 |
if adjusted_shgc is None and hasattr(window, 'drapery') and window.drapery and window.drapery.enabled:
|
|
|
754 |
else:
|
755 |
if self.debug_mode:
|
756 |
logger.debug(f"Using shading coefficient: {effective_shading_coefficient} (adjusted_shgc={adjusted_shgc}, drapery={'enabled' if hasattr(window, 'drapery') and window.drapery and window.drapery.enabled else 'disabled'})")
|
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=lat1_str,
|
770 |
orientation=window.orientation.value,
|
|
|
777 |
hour=hour,
|
778 |
month=month_int
|
779 |
)
|
780 |
+
|
781 |
# Interpolate SCL
|
782 |
if lat1 == lat2:
|
783 |
scl = scl1
|
|
|
792 |
logger.error(f"get_scl failed for latitude={latitude}, month={month}, orientation={window.orientation.value}: {str(e)}")
|
793 |
logger.warning("Using default SCL=100 W/m²")
|
794 |
scl = 100.0
|
795 |
+
|
796 |
solar_load = window.area * shgc * effective_shading_coefficient * scl
|
797 |
+
|
798 |
total_load = conduction_load + solar_load
|
799 |
if self.debug_mode:
|
800 |
logger.debug(f"Window load: conduction={conduction_load}, solar={solar_load}, total={total_load}, u_value={u_value}, shgc={shgc}, cltd={cltd}, effective_shading_coefficient={effective_shading_coefficient}")
|
801 |
+
|
802 |
return {
|
803 |
'conduction': max(conduction_load, 0.0),
|
804 |
'solar': max(solar_load, 0.0),
|
|
|
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,
|