mabuseif commited on
Commit
2a32bd2
·
verified ·
1 Parent(s): 7c6670b

Update utils/cooling_load.py

Browse files
Files changed (1) hide show
  1. utils/cooling_load.py +59 -15
utils/cooling_load.py CHANGED
@@ -4,8 +4,8 @@ Implements ASHRAE steady-state methods with Cooling Load Temperature Difference
4
  Reference: ASHRAE Handbook—Fundamentals (2017), Chapter 18, Section 18.5.
5
 
6
  Author: Dr Majed Abuseif
7
- Date: April 2025
8
- Version: 1.0.7
9
  """
10
 
11
  from typing import Dict, List, Any, Optional, Tuple
@@ -279,6 +279,8 @@ class CoolingLoadCalculator:
279
  for window in building_components.get('windows', []):
280
  for hour in range(24):
281
  adjusted_shgc = getattr(window, 'adjusted_shgc', None)
 
 
282
  load_dict = self.calculate_window_cooling_load(
283
  window=window,
284
  outdoor_temp=outdoor_conditions['temperature'],
@@ -287,7 +289,9 @@ class CoolingLoadCalculator:
287
  hour=hour,
288
  latitude=latitude,
289
  shading_coefficient=window.shading_coefficient,
290
- adjusted_shgc=adjusted_shgc
 
 
291
  )
292
  hourly_loads['windows_conduction'][hour + 1] += load_dict['conduction']
293
  hourly_loads['windows_solar'][hour + 1] += load_dict['solar']
@@ -296,6 +300,8 @@ class CoolingLoadCalculator:
296
  for skylight in building_components.get('skylights', []):
297
  for hour in range(24):
298
  adjusted_shgc = getattr(skylight, 'adjusted_shgc', None)
 
 
299
  load_dict = self.calculate_skylight_cooling_load(
300
  skylight=skylight,
301
  outdoor_temp=outdoor_conditions['temperature'],
@@ -304,7 +310,9 @@ class CoolingLoadCalculator:
304
  hour=hour,
305
  latitude=latitude,
306
  shading_coefficient=skylight.shading_coefficient,
307
- adjusted_shgc=adjusted_shgc
 
 
308
  )
309
  hourly_loads['skylights_conduction'][hour + 1] += load_dict['conduction']
310
  hourly_loads['skylights_solar'][hour + 1] += load_dict['solar']
@@ -662,7 +670,9 @@ class CoolingLoadCalculator:
662
  hour: int,
663
  latitude: str,
664
  shading_coefficient: float,
665
- adjusted_shgc: Optional[float] = None
 
 
666
  ) -> Dict[str, float]:
667
  """
668
  Calculate cooling load for a window (conduction and solar).
@@ -677,6 +687,8 @@ class CoolingLoadCalculator:
677
  latitude: Latitude (e.g., '24N')
678
  shading_coefficient: Default shading coefficient
679
  adjusted_shgc: Adjusted SHGC from external drapery calculation (optional)
 
 
680
 
681
  Returns:
682
  Dictionary with conduction, solar, and total loads in Watts
@@ -686,17 +698,31 @@ class CoolingLoadCalculator:
686
  month = self.validate_month(month)
687
  hour = self.validate_hour(hour)
688
  if self.debug_mode:
689
- logger.debug(f"calculate_window_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation={window.orientation.value}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
690
 
691
  # Conduction load
692
  cltd = outdoor_temp - indoor_temp
693
- conduction_load = window.u_value * window.area * cltd
694
 
695
  # Determine shading coefficient
696
  effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
697
  if adjusted_shgc is None and hasattr(window, 'drapery') and window.drapery and window.drapery.enabled:
698
  try:
699
- effective_shading_coefficient = window.drapery.get_shading_coefficient(window.shgc)
700
  if self.debug_mode:
701
  logger.debug(f"Using drapery shading coefficient: {effective_shading_coefficient}")
702
  except Exception as e:
@@ -720,7 +746,7 @@ class CoolingLoadCalculator:
720
  logger.warning("Using default SCL=100 W/m²")
721
  scl = 100.0
722
 
723
- solar_load = window.area * window.shgc * effective_shading_coefficient * scl
724
 
725
  total_load = conduction_load + solar_load
726
  if self.debug_mode:
@@ -746,7 +772,9 @@ class CoolingLoadCalculator:
746
  hour: int,
747
  latitude: str,
748
  shading_coefficient: float,
749
- adjusted_shgc: Optional[float] = None
 
 
750
  ) -> Dict[str, float]:
751
  """
752
  Calculate cooling load for a skylight (conduction and solar).
@@ -761,6 +789,8 @@ class CoolingLoadCalculator:
761
  latitude: Latitude (e.g., '24N')
762
  shading_coefficient: Default shading coefficient
763
  adjusted_shgc: Adjusted SHGC from external drapery calculation (optional)
 
 
764
 
765
  Returns:
766
  Dictionary with conduction, solar, and total loads in Watts
@@ -770,17 +800,31 @@ class CoolingLoadCalculator:
770
  month = self.validate_month(month)
771
  hour = self.validate_hour(hour)
772
  if self.debug_mode:
773
- logger.debug(f"calculate_skylight_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation=Horizontal")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
774
 
775
  # Conduction load
776
  cltd = outdoor_temp - indoor_temp
777
- conduction_load = skylight.u_value * skylight.area * cltd
778
 
779
  # Determine shading coefficient
780
  effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
781
  if adjusted_shgc is None and hasattr(skylight, 'drapery') and skylight.drapery and skylight.drapery.enabled:
782
  try:
783
- effective_shading_coefficient = skylight.drapery.get_shading_coefficient(skylight.shgc)
784
  if self.debug_mode:
785
  logger.debug(f"Using drapery shading coefficient: {effective_shading_coefficient}")
786
  except Exception as e:
@@ -804,7 +848,7 @@ class CoolingLoadCalculator:
804
  logger.warning("Using default SCL=100 W/m²")
805
  scl = 100.0
806
 
807
- solar_load = skylight.area * skylight.shgc * effective_shading_coefficient * scl
808
 
809
  total_load = conduction_load + solar_load
810
  if self.debug_mode:
@@ -1148,7 +1192,7 @@ if __name__ == "__main__":
1148
  components = {
1149
  'walls': [Wall(id="w1", name="North Wall", area=20.0, u_value=0.5, orientation=Orientation.NORTH, wall_group='A', solar_absorptivity=0.6)],
1150
  'roofs': [Roof(id="r1", name="Main Roof", area=100.0, u_value=0.3, orientation=Orientation.HORIZONTAL, roof_group='A', solar_absorptivity=0.6)],
1151
- 'windows': [Window(id="win1", name="South Window", area=10.0, u_value=2.8, orientation=Orientation.SOUTH, shgc=0.7, shading_coefficient=0.8)],
1152
  'doors': [Door(id="d1", name="Main Door", area=2.0, u_value=2.0, orientation=Orientation.NORTH)]
1153
  }
1154
  outdoor_conditions = {
 
4
  Reference: ASHRAE Handbook—Fundamentals (2017), Chapter 18, Section 18.5.
5
 
6
  Author: Dr Majed Abuseif
7
+ Date: May 2025
8
+ Version: 1.0.8
9
  """
10
 
11
  from typing import Dict, List, Any, Optional, Tuple
 
279
  for window in building_components.get('windows', []):
280
  for hour in range(24):
281
  adjusted_shgc = getattr(window, 'adjusted_shgc', None)
282
+ glazing_type = getattr(window, 'glazing_type', None)
283
+ frame_type = getattr(window, 'frame_type', None)
284
  load_dict = self.calculate_window_cooling_load(
285
  window=window,
286
  outdoor_temp=outdoor_conditions['temperature'],
 
289
  hour=hour,
290
  latitude=latitude,
291
  shading_coefficient=window.shading_coefficient,
292
+ adjusted_shgc=adjusted_shgc,
293
+ glazing_type=glazing_type,
294
+ frame_type=frame_type
295
  )
296
  hourly_loads['windows_conduction'][hour + 1] += load_dict['conduction']
297
  hourly_loads['windows_solar'][hour + 1] += load_dict['solar']
 
300
  for skylight in building_components.get('skylights', []):
301
  for hour in range(24):
302
  adjusted_shgc = getattr(skylight, 'adjusted_shgc', None)
303
+ glazing_type = getattr(skylight, 'glazing_type', None)
304
+ frame_type = getattr(skylight, 'frame_type', None)
305
  load_dict = self.calculate_skylight_cooling_load(
306
  skylight=skylight,
307
  outdoor_temp=outdoor_conditions['temperature'],
 
310
  hour=hour,
311
  latitude=latitude,
312
  shading_coefficient=skylight.shading_coefficient,
313
+ adjusted_shgc=adjusted_shgc,
314
+ glazing_type=glazing_type,
315
+ frame_type=frame_type
316
  )
317
  hourly_loads['skylights_conduction'][hour + 1] += load_dict['conduction']
318
  hourly_loads['skylights_solar'][hour + 1] += load_dict['solar']
 
670
  hour: int,
671
  latitude: str,
672
  shading_coefficient: float,
673
+ adjusted_shgc: Optional[float] = None,
674
+ glazing_type: Optional[str] = None,
675
+ frame_type: Optional[str] = None
676
  ) -> Dict[str, float]:
677
  """
678
  Calculate cooling load for a window (conduction and solar).
 
687
  latitude: Latitude (e.g., '24N')
688
  shading_coefficient: Default shading coefficient
689
  adjusted_shgc: Adjusted SHGC from external drapery calculation (optional)
690
+ glazing_type: Type of glazing (e.g., 'Single Clear', 'Double Tinted') (optional)
691
+ frame_type: Type of frame (e.g., 'Aluminum', 'Vinyl') (optional)
692
 
693
  Returns:
694
  Dictionary with conduction, solar, and total loads in Watts
 
698
  month = self.validate_month(month)
699
  hour = self.validate_hour(hour)
700
  if self.debug_mode:
701
+ 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}")
702
+
703
+ # Fetch U-factor and SHGC from Drapery if glazing_type and frame_type are provided
704
+ u_value = window.u_value
705
+ shgc = window.shgc
706
+ if glazing_type and frame_type:
707
+ try:
708
+ drapery = Drapery()
709
+ u_value = drapery.WINDOW_U_FACTORS.get((glazing_type, frame_type), window.u_value)
710
+ shgc = drapery.WINDOW_SHGC.get((glazing_type, frame_type), window.shgc)
711
+ if self.debug_mode:
712
+ logger.debug(f"Using Drapery values: u_value={u_value}, shgc={shgc} for glazing_type={glazing_type}, frame_type={frame_type}")
713
+ except Exception as e:
714
+ if self.debug_mode:
715
+ logger.warning(f"Error fetching Drapery values for glazing_type={glazing_type}, frame_type={frame_type}: {str(e)}. Using default u_value={u_value}, shgc={shgc}")
716
 
717
  # Conduction load
718
  cltd = outdoor_temp - indoor_temp
719
+ conduction_load = u_value * window.area * cltd
720
 
721
  # Determine shading coefficient
722
  effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
723
  if adjusted_shgc is None and hasattr(window, 'drapery') and window.drapery and window.drapery.enabled:
724
  try:
725
+ effective_shading_coefficient = window.drapery.get_shading_coefficient(shgc)
726
  if self.debug_mode:
727
  logger.debug(f"Using drapery shading coefficient: {effective_shading_coefficient}")
728
  except Exception as e:
 
746
  logger.warning("Using default SCL=100 W/m²")
747
  scl = 100.0
748
 
749
+ solar_load = window.area * shgc * effective_shading_coefficient * scl
750
 
751
  total_load = conduction_load + solar_load
752
  if self.debug_mode:
 
772
  hour: int,
773
  latitude: str,
774
  shading_coefficient: float,
775
+ adjusted_shgc: Optional[float] = None,
776
+ glazing_type: Optional[str] = None,
777
+ frame_type: Optional[str] = None
778
  ) -> Dict[str, float]:
779
  """
780
  Calculate cooling load for a skylight (conduction and solar).
 
789
  latitude: Latitude (e.g., '24N')
790
  shading_coefficient: Default shading coefficient
791
  adjusted_shgc: Adjusted SHGC from external drapery calculation (optional)
792
+ glazing_type: Type of glazing (e.g., 'Single Clear', 'Double Tinted') (optional)
793
+ frame_type: Type of frame (e.g., 'Aluminum', 'Vinyl') (optional)
794
 
795
  Returns:
796
  Dictionary with conduction, solar, and total loads in Watts
 
800
  month = self.validate_month(month)
801
  hour = self.validate_hour(hour)
802
  if self.debug_mode:
803
+ logger.debug(f"calculate_skylight_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation=Horizontal, glazing_type={glazing_type}, frame_type={frame_type}")
804
+
805
+ # Fetch U-factor and SHGC from Drapery if glazing_type and frame_type are provided
806
+ u_value = skylight.u_value
807
+ shgc = skylight.shgc
808
+ if glazing_type and frame_type:
809
+ try:
810
+ drapery = Drapery()
811
+ u_value = drapery.SKYLIGHT_U_FACTORS.get((glazing_type, frame_type), skylight.u_value)
812
+ shgc = drapery.SKYLIGHT_SHGC.get((glazing_type, frame_type), skylight.shgc)
813
+ if self.debug_mode:
814
+ logger.debug(f"Using Drapery values: u_value={u_value}, shgc={shgc} for glazing_type={glazing_type}, frame_type={frame_type}")
815
+ except Exception as e:
816
+ if self.debug_mode:
817
+ logger.warning(f"Error fetching Drapery values for glazing_type={glazing_type}, frame_type={frame_type}: {str(e)}. Using default u_value={u_value}, shgc={shgc}")
818
 
819
  # Conduction load
820
  cltd = outdoor_temp - indoor_temp
821
+ conduction_load = u_value * skylight.area * cltd
822
 
823
  # Determine shading coefficient
824
  effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
825
  if adjusted_shgc is None and hasattr(skylight, 'drapery') and skylight.drapery and skylight.drapery.enabled:
826
  try:
827
+ effective_shading_coefficient = skylight.drapery.get_shading_coefficient(shgc)
828
  if self.debug_mode:
829
  logger.debug(f"Using drapery shading coefficient: {effective_shading_coefficient}")
830
  except Exception as e:
 
848
  logger.warning("Using default SCL=100 W/m²")
849
  scl = 100.0
850
 
851
+ solar_load = skylight.area * shgc * effective_shading_coefficient * scl
852
 
853
  total_load = conduction_load + solar_load
854
  if self.debug_mode:
 
1192
  components = {
1193
  'walls': [Wall(id="w1", name="North Wall", area=20.0, u_value=0.5, orientation=Orientation.NORTH, wall_group='A', solar_absorptivity=0.6)],
1194
  'roofs': [Roof(id="r1", name="Main Roof", area=100.0, u_value=0.3, orientation=Orientation.HORIZONTAL, roof_group='A', solar_absorptivity=0.6)],
1195
+ 'windows': [Window(id="win1", name="South Window", area=10.0, u_value=2.8, orientation=Orientation.SOUTH, shgc=0.7, shading_coefficient=0.8, glazing_type='Single Clear', frame_type='Aluminum')],
1196
  'doors': [Door(id="d1", name="Main Door", area=2.0, u_value=2.0, orientation=Orientation.NORTH)]
1197
  }
1198
  outdoor_conditions = {