mabuseif commited on
Commit
813c0a4
·
verified ·
1 Parent(s): 113c089

Update utils/cooling_load.py

Browse files
Files changed (1) hide show
  1. utils/cooling_load.py +90 -64
utils/cooling_load.py CHANGED
@@ -27,6 +27,26 @@ class CoolingLoadCalculator:
27
  self.ashrae_tables = ASHRAETables()
28
  self.heat_transfer = HeatTransferCalculations()
29
  self.hours = list(range(24))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  def calculate_hourly_cooling_loads(
32
  self,
@@ -67,21 +87,10 @@ class CoolingLoadCalculator:
67
  }
68
 
69
  try:
70
- # Validate outdoor conditions
71
- valid_latitudes = ['24N', '36N', '48N']
72
- latitude = outdoor_conditions.get('latitude', '24N')
73
- if not isinstance(latitude, str) or '_' in latitude:
74
- raise ValueError(f"Invalid latitude format: {latitude}. Expected format: '24N', '36N', or '48N'")
75
- if latitude not in valid_latitudes:
76
- logger.warning(f"Latitude {latitude} not in {valid_latitudes}. Defaulting to '24N'")
77
- latitude = '24N'
78
-
79
- valid_months = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
80
- month = outdoor_conditions.get('month', 'JUL').upper()
81
- if month not in valid_months:
82
- raise ValueError(f"Invalid month: {month}. Must be one of {valid_months}")
83
-
84
- logger.debug(f"Using latitude={latitude}, month={month} for calculations")
85
 
86
  # Calculate loads for walls
87
  for wall in building_components.get('walls', []):
@@ -316,6 +325,10 @@ class CoolingLoadCalculator:
316
  Cooling load in Watts
317
  """
318
  try:
 
 
 
 
319
  cltd = self.ashrae_tables.calculate_corrected_cltd_wall(
320
  wall_group=wall.wall_group,
321
  orientation=wall.orientation.value,
@@ -357,6 +370,11 @@ class CoolingLoadCalculator:
357
  Cooling load in Watts
358
  """
359
  try:
 
 
 
 
 
360
  # Validate and map roof_group
361
  valid_roof_groups = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
362
  roof_group = roof.roof_group
@@ -366,12 +384,6 @@ class CoolingLoadCalculator:
366
  else:
367
  raise ValueError(f"Invalid roof group: {roof_group}. Must be one of {valid_roof_groups}")
368
 
369
- # Validate and map latitude
370
- valid_latitudes = ['24N', '36N', '48N']
371
- if latitude not in valid_latitudes:
372
- logger.warning(f"Latitude {latitude} not in {valid_latitudes}. Defaulting to '24N'")
373
- latitude = '24N'
374
-
375
  cltd = self.ashrae_tables.calculate_corrected_cltd_roof(
376
  roof_group=roof_group,
377
  hour=hour,
@@ -414,20 +426,10 @@ class CoolingLoadCalculator:
414
  Dictionary with conduction and solar loads in Watts
415
  """
416
  try:
417
- # Validate month
418
- valid_months = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
419
- month_upper = month.upper()
420
- if month_upper not in valid_months:
421
- raise ValueError(f"Invalid month: {month}. Must be one of {valid_months}")
422
-
423
- # Validate latitude
424
- valid_latitudes = ['24N', '36N', '48N']
425
- scl_latitude = latitude
426
- if not isinstance(latitude, str) or '_' in latitude:
427
- raise ValueError(f"Invalid latitude format: {latitude}. Expected format: '24N', '36N', or '48N'")
428
- if latitude not in valid_latitudes:
429
- logger.warning(f"Latitude {latitude} not in {valid_latitudes}. Defaulting to '24N'")
430
- scl_latitude = '24N'
431
 
432
  # Conduction load
433
  delta_t = outdoor_temp - indoor_temp
@@ -437,26 +439,40 @@ class CoolingLoadCalculator:
437
  # Note: Solar altitude is not computed directly, as ASHRAE SCL tables (via get_scl)
438
  # account for solar geometry effects based on month, orientation, hour, and latitude.
439
  logger.debug(f"Calling get_scl with month={month_upper}, orientation={window.orientation.value}, hour={hour}, latitude={scl_latitude}")
440
- try:
441
- scl = self.ashrae_tables.get_scl(
442
- month=month_upper,
443
- orientation=window.orientation.value,
444
- hour=hour,
445
- latitude=scl_latitude
446
- )
447
- except Exception as e:
448
- logger.error(f"get_scl failed: {str(e)}")
449
- # Fallback: Retry with default latitude if error involves latitude/month combination
450
- if "36N_JUL" in str(e):
451
- logger.warning(f"Retrying get_scl with fallback latitude='24N'")
 
452
  scl = self.ashrae_tables.get_scl(
453
- month=month_upper,
454
  orientation=window.orientation.value,
455
  hour=hour,
456
- latitude='24N'
457
  )
458
- else:
459
- raise ValueError(f"Failed to retrieve SCL for month={month_upper}, orientation={window.orientation.value}, hour={hour}, latitude={scl_latitude}: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
460
 
461
  solar_load = window.area * window.shgc * scl * shading_coefficient
462
 
@@ -722,7 +738,7 @@ if __name__ == "__main__":
722
  'relative_humidity': 50.0,
723
  'ground_temperature': 20.0,
724
  'month': 'Jul',
725
- 'latitude': '36N',
726
  'wind_speed': 4
727
  }
728
 
@@ -741,15 +757,25 @@ if __name__ == "__main__":
741
 
742
  building_volume = 300.0
743
 
744
- # Calculate loads
745
- try:
746
- hourly_loads = calculator.calculate_hourly_cooling_loads(
747
- building_components,
748
- outdoor_conditions,
749
- indoor_conditions,
750
- internal_loads,
751
- building_volume
752
- )
753
- print("Hourly Loads:", hourly_loads)
754
- except Exception as e:
755
- print(f"Error in example calculation: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
27
  self.ashrae_tables = ASHRAETables()
28
  self.heat_transfer = HeatTransferCalculations()
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
+
33
+ def validate_latitude(self, latitude: str) -> str:
34
+ """Validate and return a valid latitude."""
35
+ if not isinstance(latitude, str) or '_' in latitude:
36
+ logger.warning(f"Invalid latitude format: {latitude}. Defaulting to '24N'")
37
+ return '24N'
38
+ if latitude not in self.valid_latitudes:
39
+ logger.warning(f"Latitude {latitude} not in {self.valid_latitudes}. Defaulting to '24N'")
40
+ return '24N'
41
+ return latitude
42
+
43
+ def validate_month(self, month: str) -> str:
44
+ """Validate and return a valid month in uppercase."""
45
+ month_upper = month.upper()
46
+ if month_upper not in self.valid_months:
47
+ logger.warning(f"Invalid month: {month}. Defaulting to 'JUL'")
48
+ return 'JUL'
49
+ return month_upper
50
 
51
  def calculate_hourly_cooling_loads(
52
  self,
 
87
  }
88
 
89
  try:
90
+ # Validate inputs
91
+ latitude = self.validate_latitude(outdoor_conditions.get('latitude', '24N'))
92
+ month = self.validate_month(outdoor_conditions.get('month', 'JUL'))
93
+ logger.debug(f"calculate_hourly_cooling_loads: latitude={latitude}, month={month}")
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  # Calculate loads for walls
96
  for wall in building_components.get('walls', []):
 
325
  Cooling load in Watts
326
  """
327
  try:
328
+ latitude = self.validate_latitude(latitude)
329
+ month = self.validate_month(month)
330
+ logger.debug(f"calculate_wall_cooling_load: latitude={latitude}, month={month}")
331
+
332
  cltd = self.ashrae_tables.calculate_corrected_cltd_wall(
333
  wall_group=wall.wall_group,
334
  orientation=wall.orientation.value,
 
370
  Cooling load in Watts
371
  """
372
  try:
373
+ # Validate inputs
374
+ latitude = self.validate_latitude(latitude)
375
+ month = self.validate_month(month)
376
+ logger.debug(f"calculate_roof_cooling_load: latitude={latitude}, month={month}")
377
+
378
  # Validate and map roof_group
379
  valid_roof_groups = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
380
  roof_group = roof.roof_group
 
384
  else:
385
  raise ValueError(f"Invalid roof group: {roof_group}. Must be one of {valid_roof_groups}")
386
 
 
 
 
 
 
 
387
  cltd = self.ashrae_tables.calculate_corrected_cltd_roof(
388
  roof_group=roof_group,
389
  hour=hour,
 
426
  Dictionary with conduction and solar loads in Watts
427
  """
428
  try:
429
+ # Validate inputs
430
+ scl_latitude = self.validate_latitude(latitude)
431
+ month_upper = self.validate_month(month)
432
+ logger.debug(f"calculate_window_cooling_load: latitude={scl_latitude}, month={month_upper}")
 
 
 
 
 
 
 
 
 
 
433
 
434
  # Conduction load
435
  delta_t = outdoor_temp - indoor_temp
 
439
  # Note: Solar altitude is not computed directly, as ASHRAE SCL tables (via get_scl)
440
  # account for solar geometry effects based on month, orientation, hour, and latitude.
441
  logger.debug(f"Calling get_scl with month={month_upper}, orientation={window.orientation.value}, hour={hour}, latitude={scl_latitude}")
442
+
443
+ # Try different month formats to handle potential get_scl issues
444
+ month_formats = [
445
+ (month_upper, "uppercase"), # e.g., 'JUL'
446
+ (month_upper.capitalize(), "capitalized"), # e.g., 'Jul'
447
+ (str({'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6,
448
+ 'JUL': 7, 'AUG': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12}[month_upper]), "numeric") # e.g., '7'
449
+ ]
450
+
451
+ scl = None
452
+ for month_value, format_name in month_formats:
453
+ try:
454
+ logger.debug(f"Trying get_scl with month format '{format_name}': month={month_value}")
455
  scl = self.ashrae_tables.get_scl(
456
+ month=month_value,
457
  orientation=window.orientation.value,
458
  hour=hour,
459
+ latitude=scl_latitude
460
  )
461
+ logger.debug(f"Success with month format '{format_name}'")
462
+ break
463
+ except Exception as e:
464
+ logger.warning(f"get_scl failed with month format '{format_name}': {str(e)}")
465
+ continue
466
+
467
+ # Final fallback: Use latitude='24N' with default month='JUL'
468
+ if scl is None:
469
+ logger.warning(f"All month formats failed. Retrying with fallback latitude='24N', month='JUL'")
470
+ scl = self.ashrae_tables.get_scl(
471
+ month='JUL',
472
+ orientation=window.orientation.value,
473
+ hour=hour,
474
+ latitude='24N'
475
+ )
476
 
477
  solar_load = window.area * window.shgc * scl * shading_coefficient
478
 
 
738
  'relative_humidity': 50.0,
739
  'ground_temperature': 20.0,
740
  'month': 'Jul',
741
+ 'latitude': '24N',
742
  'wind_speed': 4
743
  }
744
 
 
757
 
758
  building_volume = 300.0
759
 
760
+ # Test with multiple latitudes and months
761
+ test_cases = [
762
+ {'latitude': '24N', 'month': 'Jul'},
763
+ {'latitude': '36N', 'month': 'Jul'},
764
+ {'latitude': '48N', 'month': 'Jan'},
765
+ {'latitude': 'invalid', 'month': 'invalid'} # Test invalid inputs
766
+ ]
767
+
768
+ for case in test_cases:
769
+ outdoor_conditions['latitude'] = case['latitude']
770
+ outdoor_conditions['month'] = case['month']
771
+ try:
772
+ hourly_loads = calculator.calculate_hourly_cooling_loads(
773
+ building_components,
774
+ outdoor_conditions,
775
+ indoor_conditions,
776
+ internal_loads,
777
+ building_volume
778
+ )
779
+ print(f"Success for latitude={case['latitude']}, month={case['month']}: Hourly Loads calculated")
780
+ except Exception as e:
781
+ print(f"Error for latitude={case['latitude']}, month={case['month']}: {str(e)}")