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,
|