mabuseif commited on
Commit
7007eef
·
verified ·
1 Parent(s): 2004b86

Upload cooling_load.py

Browse files
Files changed (1) hide show
  1. utils/cooling_load.py +19 -120
utils/cooling_load.py CHANGED
@@ -5,7 +5,7 @@ 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
@@ -14,7 +14,7 @@ import logging
14
  from data.ashrae_tables import ASHRAETables
15
  from utils.heat_transfer import HeatTransferCalculations
16
  from utils.psychrometrics import Psychrometrics
17
- from app.component_selection import Wall, Roof, Window, Door, Skylight, Orientation
18
  from data.drapery import Drapery
19
 
20
  # Set up logging
@@ -220,7 +220,6 @@ class CoolingLoadCalculator:
220
  'windows_conduction': {h: 0.0 for h in range(1, 25)},
221
  'windows_solar': {h: 0.0 for h in range(1, 25)},
222
  'doors': {h: 0.0 for h in range(1, 25)},
223
- 'skylights': {h: 0.0 for h in range(1, 25)}, # Added for skylights
224
  'people_sensible': {h: 0.0 for h in range(1, 25)},
225
  'people_latent': {h: 0.0 for h in range(1, 25)},
226
  'lights': {h: 0.0 for h in range(1, 25)},
@@ -238,7 +237,7 @@ class CoolingLoadCalculator:
238
  outdoor_conditions['temperature'],
239
  indoor_conditions['temperature'],
240
  outdoor_conditions.get('relative_humidity', 50.0),
241
- indoor_conditions.get('relative_hierarchy', 50.0)
242
  )
243
 
244
  latitude = self.validate_latitude(outdoor_conditions.get('latitude', '32N'))
@@ -284,10 +283,7 @@ class CoolingLoadCalculator:
284
  month=month,
285
  hour=hour,
286
  latitude=latitude,
287
- shading_coefficient=window.shading_coefficient,
288
- adjusted_shgc=window.shgc, # Default to base SHGC
289
- glazing_type=window.glazing_type,
290
- frame_type=window.frame_type
291
  )
292
  hourly_loads['windows_conduction'][hour + 1] += load_dict['conduction']
293
  hourly_loads['windows_solar'][hour + 1] += load_dict['solar']
@@ -302,23 +298,6 @@ class CoolingLoadCalculator:
302
  )
303
  hourly_loads['doors'][hour + 1] += load
304
 
305
- # Calculate loads for skylights
306
- for skylight in building_components.get('skylights', []):
307
- for hour in range(24):
308
- load_dict = self.calculate_skylight_cooling_load(
309
- skylight=skylight,
310
- outdoor_temp=outdoor_conditions['temperature'],
311
- indoor_temp=indoor_conditions['temperature'],
312
- month=month,
313
- hour=hour,
314
- latitude=latitude,
315
- shading_coefficient=skylight.shading_coefficient,
316
- adjusted_shgc=skylight.shgc, # Default to base SHGC
317
- glazing_type=skylight.glazing_type,
318
- frame_type=skylight.frame_type
319
- )
320
- hourly_loads['skylights'][hour + 1] += load_dict['total']
321
-
322
  # Calculate internal loads
323
  for hour in range(24):
324
  # People loads
@@ -403,7 +382,6 @@ class CoolingLoadCalculator:
403
  hourly_loads['windows_conduction'][hour],
404
  hourly_loads['windows_solar'][hour],
405
  hourly_loads['doors'][hour],
406
- hourly_loads['skylights'][hour], # Added for skylights
407
  hourly_loads['people_sensible'][hour],
408
  hourly_loads['people_latent'][hour],
409
  hourly_loads['lights'][hour],
@@ -425,7 +403,6 @@ class CoolingLoadCalculator:
425
  'windows_conduction': hourly_loads['windows_conduction'][design_hour],
426
  'windows_solar': hourly_loads['windows_solar'][design_hour],
427
  'doors': hourly_loads['doors'][design_hour],
428
- 'skylights': hourly_loads['skylights'][design_hour], # Added for skylights
429
  'people_sensible': hourly_loads['people_sensible'][design_hour],
430
  'people_latent': hourly_loads['people_latent'][design_hour],
431
  'lights': hourly_loads['lights'][design_hour],
@@ -462,7 +439,6 @@ class CoolingLoadCalculator:
462
  design_loads['windows_conduction'] +
463
  design_loads['windows_solar'] +
464
  design_loads['doors'] +
465
- design_loads['skylights'] + # Added for skylights
466
  design_loads['people_sensible'] +
467
  design_loads['lights'] +
468
  design_loads['equipment_sensible'] +
@@ -658,10 +634,7 @@ class CoolingLoadCalculator:
658
  month: str,
659
  hour: int,
660
  latitude: str,
661
- shading_coefficient: float,
662
- adjusted_shgc: float,
663
- glazing_type: Any,
664
- frame_type: Any
665
  ) -> Dict[str, float]:
666
  """
667
  Calculate cooling load for a window (conduction and solar).
@@ -675,9 +648,6 @@ class CoolingLoadCalculator:
675
  hour: Hour of the day
676
  latitude: Latitude (e.g., '24N')
677
  shading_coefficient: Default shading coefficient
678
- adjusted_shgc: Adjusted SHGC accounting for drapery (from Drapery.get_shading_coefficient)
679
- glazing_type: Window glazing type
680
- frame_type: Window frame type
681
 
682
  Returns:
683
  Dictionary with conduction, solar, and total loads in Watts
@@ -693,10 +663,19 @@ class CoolingLoadCalculator:
693
  cltd = outdoor_temp - indoor_temp
694
  conduction_load = window.u_value * window.area * cltd
695
 
696
- # Use adjusted_shgc if provided, otherwise fall back to shading_coefficient
697
- effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
698
- if self.debug_mode:
699
- logger.debug(f"Window {window.name}: adjusted_shgc={adjusted_shgc}, effective_shading_coefficient={effective_shading_coefficient}")
 
 
 
 
 
 
 
 
 
700
 
701
  # Solar load
702
  try:
@@ -729,85 +708,6 @@ class CoolingLoadCalculator:
729
  logger.error(f"Error in calculate_window_cooling_load: {str(e)}")
730
  raise Exception(f"Error in calculate_window_cooling_load: {str(e)}")
731
 
732
- def calculate_skylight_cooling_load(
733
- self,
734
- skylight: Skylight,
735
- outdoor_temp: float,
736
- indoor_temp: float,
737
- month: str,
738
- hour: int,
739
- latitude: str,
740
- shading_coefficient: float,
741
- adjusted_shgc: float,
742
- glazing_type: Any,
743
- frame_type: Any
744
- ) -> Dict[str, float]:
745
- """
746
- Calculate cooling load for a skylight (conduction and solar).
747
- Reference: ASHRAE Handbook—Fundamentals (2017), Chapter 18, Equations 18.12-18.13.
748
-
749
- Args:
750
- skylight: Skylight component
751
- outdoor_temp: Outdoor temperature (°C)
752
- indoor_temp: Indoor temperature (°C)
753
- month: Design month
754
- hour: Hour of the day
755
- latitude: Latitude (e.g., '24N')
756
- shading_coefficient: Default shading coefficient
757
- adjusted_shgc: Adjusted SHGC accounting for drapery (from Drapery.get_shading_coefficient)
758
- glazing_type: Skylight glazing type
759
- frame_type: Skylight frame type
760
-
761
- Returns:
762
- Dictionary with conduction, solar, and total loads in Watts
763
- """
764
- try:
765
- latitude = self.validate_latitude(latitude)
766
- month = self.validate_month(month)
767
- hour = self.validate_hour(hour)
768
- if self.debug_mode:
769
- logger.debug(f"calculate_skylight_cooling_load: latitude={latitude}, month={month}, hour={hour}, orientation=Horizontal")
770
-
771
- # Conduction load
772
- cltd = outdoor_temp - indoor_temp
773
- conduction_load = skylight.u_value * skylight.area * cltd
774
-
775
- # Use adjusted_shgc if provided, otherwise fall back to shading_coefficient
776
- effective_shading_coefficient = adjusted_shgc if adjusted_shgc is not None else shading_coefficient
777
- if self.debug_mode:
778
- logger.debug(f"Skylight {skylight.name}: adjusted_shgc={adjusted_shgc}, effective_shading_coefficient={effective_shading_coefficient}")
779
-
780
- # Solar load (skylights use horizontal orientation)
781
- try:
782
- scl = self.ashrae_tables.get_scl(
783
- latitude=latitude,
784
- month=month,
785
- orientation='Horizontal',
786
- hour=hour
787
- )
788
- except Exception as e:
789
- if self.debug_mode:
790
- logger.error(f"get_scl failed for latitude={latitude}, month={month}, orientation=Horizontal: {str(e)}")
791
- logger.warning("Using default SCL=100 W/m²")
792
- scl = 100.0
793
-
794
- solar_load = skylight.area * skylight.shgc * effective_shading_coefficient * scl
795
-
796
- total_load = conduction_load + solar_load
797
- if self.debug_mode:
798
- logger.debug(f"Skylight load: conduction={conduction_load}, solar={solar_load}, total={total_load}, effective_shading_coefficient={effective_shading_coefficient}")
799
-
800
- return {
801
- 'conduction': max(conduction_load, 0.0),
802
- 'solar': max(solar_load, 0.0),
803
- 'total': max(total_load, 0.0)
804
- }
805
-
806
- except Exception as e:
807
- if self.debug_mode:
808
- logger.error(f"Error in calculate_skylight_cooling_load: {str(e)}")
809
- raise Exception(f"Error in calculate_skylight_cooling_load: {str(e)}")
810
-
811
  def calculate_door_cooling_load(
812
  self,
813
  door: Door,
@@ -1136,8 +1036,7 @@ if __name__ == "__main__":
1136
  'walls': [Wall(id="w1", name="North Wall", area=20.0, u_value=0.5, orientation=Orientation.NORTH, wall_group='A', solar_absorptivity=0.6)],
1137
  'roofs': [Roof(id="r1", name="Main Roof", area=100.0, u_value=0.3, orientation=Orientation.HORIZONTAL, roof_group='A', solar_absorptivity=0.6)],
1138
  'windows': [Window(id="win1", name="South Window", area=10.0, u_value=2.8, orientation=Orientation.SOUTH, shgc=0.7, shading_coefficient=0.8)],
1139
- 'doors': [Door(id="d1", name="Main Door", area=2.0, u_value=2.0, orientation=Orientation.NORTH)],
1140
- 'skylights': [Skylight(id="sky1", name="Roof Skylight", area=5.0, u_value=3.0, shgc=0.6, shading_coefficient=0.9)]
1141
  }
1142
  outdoor_conditions = {
1143
  'temperature': 35.0,
 
5
 
6
  Author: Dr Majed Abuseif
7
  Date: April 2025
8
+ Version: 1.0.6
9
  """
10
 
11
  from typing import Dict, List, Any, Optional, Tuple
 
14
  from data.ashrae_tables import ASHRAETables
15
  from utils.heat_transfer import HeatTransferCalculations
16
  from utils.psychrometrics import Psychrometrics
17
+ from app.component_selection import Wall, Roof, Window, Door, Orientation
18
  from data.drapery import Drapery
19
 
20
  # Set up logging
 
220
  'windows_conduction': {h: 0.0 for h in range(1, 25)},
221
  'windows_solar': {h: 0.0 for h in range(1, 25)},
222
  'doors': {h: 0.0 for h in range(1, 25)},
 
223
  'people_sensible': {h: 0.0 for h in range(1, 25)},
224
  'people_latent': {h: 0.0 for h in range(1, 25)},
225
  'lights': {h: 0.0 for h in range(1, 25)},
 
237
  outdoor_conditions['temperature'],
238
  indoor_conditions['temperature'],
239
  outdoor_conditions.get('relative_humidity', 50.0),
240
+ indoor_conditions.get('relative_humidity', 50.0)
241
  )
242
 
243
  latitude = self.validate_latitude(outdoor_conditions.get('latitude', '32N'))
 
283
  month=month,
284
  hour=hour,
285
  latitude=latitude,
286
+ shading_coefficient=window.shading_coefficient
 
 
 
287
  )
288
  hourly_loads['windows_conduction'][hour + 1] += load_dict['conduction']
289
  hourly_loads['windows_solar'][hour + 1] += load_dict['solar']
 
298
  )
299
  hourly_loads['doors'][hour + 1] += load
300
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  # Calculate internal loads
302
  for hour in range(24):
303
  # People loads
 
382
  hourly_loads['windows_conduction'][hour],
383
  hourly_loads['windows_solar'][hour],
384
  hourly_loads['doors'][hour],
 
385
  hourly_loads['people_sensible'][hour],
386
  hourly_loads['people_latent'][hour],
387
  hourly_loads['lights'][hour],
 
403
  'windows_conduction': hourly_loads['windows_conduction'][design_hour],
404
  'windows_solar': hourly_loads['windows_solar'][design_hour],
405
  'doors': hourly_loads['doors'][design_hour],
 
406
  'people_sensible': hourly_loads['people_sensible'][design_hour],
407
  'people_latent': hourly_loads['people_latent'][design_hour],
408
  'lights': hourly_loads['lights'][design_hour],
 
439
  design_loads['windows_conduction'] +
440
  design_loads['windows_solar'] +
441
  design_loads['doors'] +
 
442
  design_loads['people_sensible'] +
443
  design_loads['lights'] +
444
  design_loads['equipment_sensible'] +
 
634
  month: str,
635
  hour: int,
636
  latitude: str,
637
+ shading_coefficient: float
 
 
 
638
  ) -> Dict[str, float]:
639
  """
640
  Calculate cooling load for a window (conduction and solar).
 
648
  hour: Hour of the day
649
  latitude: Latitude (e.g., '24N')
650
  shading_coefficient: Default shading coefficient
 
 
 
651
 
652
  Returns:
653
  Dictionary with conduction, solar, and total loads in Watts
 
663
  cltd = outdoor_temp - indoor_temp
664
  conduction_load = window.u_value * window.area * cltd
665
 
666
+ # Determine shading coefficient
667
+ effective_shading_coefficient = shading_coefficient
668
+ if hasattr(window, 'drapery') and window.drapery and window.drapery.enabled:
669
+ try:
670
+ effective_shading_coefficient = window.drapery.get_shading_coefficient(window.shgc)
671
+ if self.debug_mode:
672
+ logger.debug(f"Using drapery shading coefficient: {effective_shading_coefficient}")
673
+ except Exception as e:
674
+ if self.debug_mode:
675
+ logger.warning(f"Error getting drapery shading coefficient: {str(e)}. Using default shading_coefficient={shading_coefficient}")
676
+ else:
677
+ if self.debug_mode:
678
+ logger.debug(f"No enabled drapery. Using default shading_coefficient={shading_coefficient}")
679
 
680
  # Solar load
681
  try:
 
708
  logger.error(f"Error in calculate_window_cooling_load: {str(e)}")
709
  raise Exception(f"Error in calculate_window_cooling_load: {str(e)}")
710
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
711
  def calculate_door_cooling_load(
712
  self,
713
  door: Door,
 
1036
  'walls': [Wall(id="w1", name="North Wall", area=20.0, u_value=0.5, orientation=Orientation.NORTH, wall_group='A', solar_absorptivity=0.6)],
1037
  'roofs': [Roof(id="r1", name="Main Roof", area=100.0, u_value=0.3, orientation=Orientation.HORIZONTAL, roof_group='A', solar_absorptivity=0.6)],
1038
  'windows': [Window(id="win1", name="South Window", area=10.0, u_value=2.8, orientation=Orientation.SOUTH, shgc=0.7, shading_coefficient=0.8)],
1039
+ 'doors': [Door(id="d1", name="Main Door", area=2.0, u_value=2.0, orientation=Orientation.NORTH)]
 
1040
  }
1041
  outdoor_conditions = {
1042
  'temperature': 35.0,