mabuseif commited on
Commit
82ed6c9
·
verified ·
1 Parent(s): 7938e5f

Update utils/cooling_load.py

Browse files
Files changed (1) hide show
  1. utils/cooling_load.py +37 -36
utils/cooling_load.py CHANGED
@@ -29,7 +29,7 @@ class CoolingLoadCalculator:
29
  self.hours = list(range(24))
30
  self.valid_latitudes = ['24N', '36N', '48N']
31
  self.valid_months = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
32
- self.valid_wall_groups = ['A', 'B', 'C', 'D'] # Adjusted to common ASHRAE groups
33
  self.valid_roof_groups = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
34
 
35
  def validate_latitude(self, latitude: Any) -> str:
@@ -46,16 +46,21 @@ class CoolingLoadCalculator:
46
  if not isinstance(latitude, str):
47
  latitude = str(latitude)
48
 
49
- # Remove whitespace and convert to uppercase
50
  latitude = latitude.strip().upper()
51
 
 
 
 
 
 
 
 
 
52
  # Handle formats like '31.973N', '1_31.973N'
53
- if '_' in latitude or '.' in latitude:
54
- # Extract numeric part
55
  num_part = ''.join(c for c in latitude if c.isdigit() or c == '.')
56
  try:
57
  lat_val = float(num_part)
58
- # Map to closest valid latitude
59
  if lat_val <= 30:
60
  return '24N'
61
  elif lat_val <= 42:
@@ -142,7 +147,7 @@ class CoolingLoadCalculator:
142
  # Validate inputs
143
  latitude = self.validate_latitude(outdoor_conditions.get('latitude', '24N'))
144
  month = self.validate_month(outdoor_conditions.get('month', 'JUL'))
145
- logger.debug(f"calculate_hourly_cooling_loads: latitude={latitude}, month={month}")
146
 
147
  # Calculate loads for walls
148
  for wall in building_components.get('walls', []):
@@ -384,7 +389,6 @@ class CoolingLoadCalculator:
384
  # Validate wall_group
385
  wall_group = str(wall.wall_group).upper()
386
  if wall_group not in self.valid_wall_groups:
387
- # Map numeric groups to letters (e.g., '1' -> 'A')
388
  numeric_map = {'1': 'A', '2': 'B', '3': 'C', '4': 'D'}
389
  if wall_group in numeric_map:
390
  wall_group = numeric_map[wall_group]
@@ -407,7 +411,7 @@ class CoolingLoadCalculator:
407
  except Exception as e:
408
  logger.error(f"calculate_corrected_cltd_wall failed for wall_group={wall_group}: {str(e)}")
409
  logger.warning("Using default CLTD=10.0°C")
410
- cltd = 10.0 # Conservative fallback
411
 
412
  load = wall.u_value * wall.area * cltd
413
  logger.debug(f"Wall load: u_value={wall.u_value}, area={wall.area}, cltd={cltd}, load={load}")
@@ -445,7 +449,6 @@ class CoolingLoadCalculator:
445
  month = self.validate_month(month)
446
  logger.debug(f"calculate_roof_cooling_load: latitude={latitude}, month={month}, roof_group={roof.roof_group}")
447
 
448
- # Validate and map roof_group
449
  roof_group = str(roof.roof_group).upper()
450
  if roof_group not in self.valid_roof_groups:
451
  logger.warning(f"Invalid roof group: {roof_group}. Defaulting to 'A'")
@@ -464,7 +467,7 @@ class CoolingLoadCalculator:
464
  except Exception as e:
465
  logger.error(f"calculate_corrected_cltd_roof failed for roof_group={roof_group}: {str(e)}")
466
  logger.warning("Using default CLTD=10.0°C")
467
- cltd = 10.0 # Conservative fallback
468
 
469
  load = roof.u_value * roof.area * cltd
470
  logger.debug(f"Roof load: u_value={roof.u_value}, area={roof.area}, cltd={cltd}, load={load}")
@@ -502,7 +505,7 @@ class CoolingLoadCalculator:
502
  try:
503
  scl_latitude = self.validate_latitude(latitude)
504
  month_upper = self.validate_month(month)
505
- logger.debug(f"calculate_window_cooling_load: latitude={scl_latitude}, month={month_upper}, orientation={window.orientation.value}")
506
 
507
  # Conduction load
508
  delta_t = outdoor_temp - indoor_temp
@@ -511,18 +514,17 @@ class CoolingLoadCalculator:
511
  # Solar load
512
  logger.debug(f"Calling get_scl with month={month_upper}, orientation={window.orientation.value}, hour={hour}, latitude={scl_latitude}")
513
 
514
- # Try different month formats to handle potential get_scl issues
515
  month_formats = [
516
- (month_upper, "uppercase"), # e.g., 'JUL'
517
- (month_upper.capitalize(), "capitalized"), # e.g., 'Jul'
518
  (str({'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6,
519
- 'JUL': 7, 'AUG': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12}[month_upper]), "numeric") # e.g., '7'
520
  ]
521
 
522
  scl = None
523
  for month_value, format_name in month_formats:
524
  try:
525
- logger.debug(f"Trying get_scl with month format '{format_name}': month={month_value}")
526
  scl = self.ashrae_tables.get_scl(
527
  latitude=scl_latitude,
528
  month=month_value,
@@ -535,15 +537,19 @@ class CoolingLoadCalculator:
535
  logger.warning(f"get_scl failed with month format '{format_name}': {str(e)}")
536
  continue
537
 
538
- # Final fallback: Use latitude='24N' with default month='JUL'
539
  if scl is None:
540
  logger.warning(f"All month formats failed. Retrying with fallback latitude='24N', month='JUL'")
541
- scl = self.ashrae_tables.get_scl(
542
- latitude='24N',
543
- month='JUL',
544
- orientation=window.orientation.value,
545
- hour=hour
546
- )
 
 
 
 
 
547
 
548
  solar_load = window.area * window.shgc * scl * shading_coefficient
549
 
@@ -751,10 +757,9 @@ class CoolingLoadCalculator:
751
  air_changes_per_hour = (flow_rate * 3600) / building_volume
752
  sensible_load = 1.2 * flow_rate * 1000 * (outdoor_temp - indoor_temp)
753
 
754
- # Calculate humidity ratio difference
755
  logger.debug(f"Calculating outdoor humidity ratio: temp={outdoor_temp}°C, rh={outdoor_rh}%")
756
  try:
757
- outdoor_rh = min(max(outdoor_rh, 0), 100) # Clamp RH to 0-100
758
  outdoor_w = self.heat_transfer.psychrometrics.humidity_ratio(outdoor_temp, outdoor_rh)
759
  except Exception as e:
760
  logger.error(f"Failed to calculate outdoor humidity ratio: {str(e)}")
@@ -763,7 +768,7 @@ class CoolingLoadCalculator:
763
 
764
  logger.debug(f"Calculating indoor humidity ratio: temp={indoor_temp}°C, rh={indoor_rh}%")
765
  try:
766
- indoor_rh = min(max(indoor_rh, 0), 100) # Clamp RH to 0-100
767
  indoor_w = self.heat_transfer.psychrometrics.humidity_ratio(indoor_temp, indoor_rh)
768
  except Exception as e:
769
  logger.error(f"Failed to calculate indoor humidity ratio: {str(e)}")
@@ -811,10 +816,9 @@ class CoolingLoadCalculator:
811
 
812
  sensible_load = 1.2 * flow_rate * 1000 * (outdoor_temp - indoor_temp)
813
 
814
- # Calculate humidity ratio difference
815
  logger.debug(f"Calculating outdoor humidity ratio: temp={outdoor_temp}°C, rh={outdoor_rh}%")
816
  try:
817
- outdoor_rh = min(max(outdoor_rh, 0), 100) # Clamp RH to 0-100
818
  outdoor_w = self.heat_transfer.psychrometrics.humidity_ratio(outdoor_temp, outdoor_rh)
819
  except Exception as e:
820
  logger.error(f"Failed to calculate outdoor humidity ratio: {str(e)}")
@@ -823,7 +827,7 @@ class CoolingLoadCalculator:
823
 
824
  logger.debug(f"Calculating indoor humidity ratio: temp={indoor_temp}°C, rh={indoor_rh}%")
825
  try:
826
- indoor_rh = min(max(indoor_rh, 0), 100) # Clamp RH to 0-100
827
  indoor_w = self.heat_transfer.psychrometrics.humidity_ratio(indoor_temp, indoor_rh)
828
  except Exception as e:
829
  logger.error(f"Failed to calculate indoor humidity ratio: {str(e)}")
@@ -845,17 +849,15 @@ class CoolingLoadCalculator:
845
 
846
 
847
  if __name__ == "__main__":
848
- # Example usage for testing
849
  calculator = CoolingLoadCalculator()
850
 
851
- # Dummy inputs
852
  building_components = {
853
  'walls': [Wall(
854
  name="North Wall",
855
  orientation=Orientation.NORTH,
856
  area=20.0,
857
  u_value=0.5,
858
- wall_group="1" # Will be mapped to 'A'
859
  )],
860
  'roofs': [Roof(
861
  name="Main Roof",
@@ -905,13 +907,12 @@ if __name__ == "__main__":
905
 
906
  building_volume = 300.0
907
 
908
- # Test with multiple latitudes, months, and wall groups
909
  test_cases = [
910
  {'latitude': '24N', 'month': 'Jul', 'wall_group': 'A'},
911
  {'latitude': '36N', 'month': 'Jul', 'wall_group': 'B'},
912
- {'latitude': '48N', 'month': 'Jan', 'wall_group': '1'}, # Should map to 'A'
913
- {'latitude': '1_31.973N', 'month': 'Jul', 'wall_group': 'invalid'}, # Should default to 'A'
914
- {'latitude': 'invalid', 'month': 'invalid', 'wall_group': '2'} # Should map to 'B'
915
  ]
916
 
917
  for case in test_cases:
 
29
  self.hours = list(range(24))
30
  self.valid_latitudes = ['24N', '36N', '48N']
31
  self.valid_months = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
32
+ self.valid_wall_groups = ['A', 'B', 'C', 'D']
33
  self.valid_roof_groups = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
34
 
35
  def validate_latitude(self, latitude: Any) -> str:
 
46
  if not isinstance(latitude, str):
47
  latitude = str(latitude)
48
 
 
49
  latitude = latitude.strip().upper()
50
 
51
+ # Handle concatenated formats like '24N_JUL'
52
+ if '_' in latitude:
53
+ parts = latitude.split('_')
54
+ if len(parts) > 1:
55
+ lat_part = parts[0]
56
+ logger.warning(f"Detected concatenated input: {latitude}. Using latitude={lat_part}")
57
+ latitude = lat_part
58
+
59
  # Handle formats like '31.973N', '1_31.973N'
60
+ if '.' in latitude or any(c.isdigit() for c in latitude):
 
61
  num_part = ''.join(c for c in latitude if c.isdigit() or c == '.')
62
  try:
63
  lat_val = float(num_part)
 
64
  if lat_val <= 30:
65
  return '24N'
66
  elif lat_val <= 42:
 
147
  # Validate inputs
148
  latitude = self.validate_latitude(outdoor_conditions.get('latitude', '24N'))
149
  month = self.validate_month(outdoor_conditions.get('month', 'JUL'))
150
+ logger.debug(f"calculate_hourly_cooling_loads: latitude={latitude}, month={month}, outdoor_conditions={outdoor_conditions}")
151
 
152
  # Calculate loads for walls
153
  for wall in building_components.get('walls', []):
 
389
  # Validate wall_group
390
  wall_group = str(wall.wall_group).upper()
391
  if wall_group not in self.valid_wall_groups:
 
392
  numeric_map = {'1': 'A', '2': 'B', '3': 'C', '4': 'D'}
393
  if wall_group in numeric_map:
394
  wall_group = numeric_map[wall_group]
 
411
  except Exception as e:
412
  logger.error(f"calculate_corrected_cltd_wall failed for wall_group={wall_group}: {str(e)}")
413
  logger.warning("Using default CLTD=10.0°C")
414
+ cltd = 10.0
415
 
416
  load = wall.u_value * wall.area * cltd
417
  logger.debug(f"Wall load: u_value={wall.u_value}, area={wall.area}, cltd={cltd}, load={load}")
 
449
  month = self.validate_month(month)
450
  logger.debug(f"calculate_roof_cooling_load: latitude={latitude}, month={month}, roof_group={roof.roof_group}")
451
 
 
452
  roof_group = str(roof.roof_group).upper()
453
  if roof_group not in self.valid_roof_groups:
454
  logger.warning(f"Invalid roof group: {roof_group}. Defaulting to 'A'")
 
467
  except Exception as e:
468
  logger.error(f"calculate_corrected_cltd_roof failed for roof_group={roof_group}: {str(e)}")
469
  logger.warning("Using default CLTD=10.0°C")
470
+ cltd = 10.0
471
 
472
  load = roof.u_value * roof.area * cltd
473
  logger.debug(f"Roof load: u_value={roof.u_value}, area={roof.area}, cltd={cltd}, load={load}")
 
505
  try:
506
  scl_latitude = self.validate_latitude(latitude)
507
  month_upper = self.validate_month(month)
508
+ logger.debug(f"calculate_window_cooling_load: latitude={latitude} -> {scl_latitude}, month={month} -> {month_upper}, orientation={window.orientation.value}")
509
 
510
  # Conduction load
511
  delta_t = outdoor_temp - indoor_temp
 
514
  # Solar load
515
  logger.debug(f"Calling get_scl with month={month_upper}, orientation={window.orientation.value}, hour={hour}, latitude={scl_latitude}")
516
 
 
517
  month_formats = [
518
+ (month_upper, "uppercase"),
519
+ (month_upper.capitalize(), "capitalized"),
520
  (str({'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6,
521
+ 'JUL': 7, 'AUG': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12}[month_upper]), "numeric")
522
  ]
523
 
524
  scl = None
525
  for month_value, format_name in month_formats:
526
  try:
527
+ logger.debug(f"Trying get_scl with month format '{format_name}': month={month_value}, latitude={scl_latitude}")
528
  scl = self.ashrae_tables.get_scl(
529
  latitude=scl_latitude,
530
  month=month_value,
 
537
  logger.warning(f"get_scl failed with month format '{format_name}': {str(e)}")
538
  continue
539
 
 
540
  if scl is None:
541
  logger.warning(f"All month formats failed. Retrying with fallback latitude='24N', month='JUL'")
542
+ try:
543
+ scl = self.ashrae_tables.get_scl(
544
+ latitude='24N',
545
+ month='JUL',
546
+ orientation=window.orientation.value,
547
+ hour=hour
548
+ )
549
+ except Exception as e:
550
+ logger.error(f"Fallback get_scl failed: {str(e)}")
551
+ logger.warning("Using default SCL=100 W/m²")
552
+ scl = 100.0 # Conservative fallback
553
 
554
  solar_load = window.area * window.shgc * scl * shading_coefficient
555
 
 
757
  air_changes_per_hour = (flow_rate * 3600) / building_volume
758
  sensible_load = 1.2 * flow_rate * 1000 * (outdoor_temp - indoor_temp)
759
 
 
760
  logger.debug(f"Calculating outdoor humidity ratio: temp={outdoor_temp}°C, rh={outdoor_rh}%")
761
  try:
762
+ outdoor_rh = min(max(outdoor_rh, 0), 100)
763
  outdoor_w = self.heat_transfer.psychrometrics.humidity_ratio(outdoor_temp, outdoor_rh)
764
  except Exception as e:
765
  logger.error(f"Failed to calculate outdoor humidity ratio: {str(e)}")
 
768
 
769
  logger.debug(f"Calculating indoor humidity ratio: temp={indoor_temp}°C, rh={indoor_rh}%")
770
  try:
771
+ indoor_rh = min(max(indoor_rh, 0), 100)
772
  indoor_w = self.heat_transfer.psychrometrics.humidity_ratio(indoor_temp, indoor_rh)
773
  except Exception as e:
774
  logger.error(f"Failed to calculate indoor humidity ratio: {str(e)}")
 
816
 
817
  sensible_load = 1.2 * flow_rate * 1000 * (outdoor_temp - indoor_temp)
818
 
 
819
  logger.debug(f"Calculating outdoor humidity ratio: temp={outdoor_temp}°C, rh={outdoor_rh}%")
820
  try:
821
+ outdoor_rh = min(max(outdoor_rh, 0), 100)
822
  outdoor_w = self.heat_transfer.psychrometrics.humidity_ratio(outdoor_temp, outdoor_rh)
823
  except Exception as e:
824
  logger.error(f"Failed to calculate outdoor humidity ratio: {str(e)}")
 
827
 
828
  logger.debug(f"Calculating indoor humidity ratio: temp={indoor_temp}°C, rh={indoor_rh}%")
829
  try:
830
+ indoor_rh = min(max(indoor_rh, 0), 100)
831
  indoor_w = self.heat_transfer.psychrometrics.humidity_ratio(indoor_temp, indoor_rh)
832
  except Exception as e:
833
  logger.error(f"Failed to calculate indoor humidity ratio: {str(e)}")
 
849
 
850
 
851
  if __name__ == "__main__":
 
852
  calculator = CoolingLoadCalculator()
853
 
 
854
  building_components = {
855
  'walls': [Wall(
856
  name="North Wall",
857
  orientation=Orientation.NORTH,
858
  area=20.0,
859
  u_value=0.5,
860
+ wall_group="1"
861
  )],
862
  'roofs': [Roof(
863
  name="Main Roof",
 
907
 
908
  building_volume = 300.0
909
 
 
910
  test_cases = [
911
  {'latitude': '24N', 'month': 'Jul', 'wall_group': 'A'},
912
  {'latitude': '36N', 'month': 'Jul', 'wall_group': 'B'},
913
+ {'latitude': '48N', 'month': 'Jan', 'wall_group': '1'},
914
+ {'latitude': '24N_JUL', 'month': 'Jul', 'wall_group': 'invalid'},
915
+ {'latitude': 'invalid', 'month': 'invalid', 'wall_group': '2'}
916
  ]
917
 
918
  for case in test_cases: