mabuseif commited on
Commit
03fb307
·
verified ·
1 Parent(s): 7f92f98

Update data/calculation.py

Browse files
Files changed (1) hide show
  1. data/calculation.py +39 -13
data/calculation.py CHANGED
@@ -308,7 +308,11 @@ class TFMCalculations:
308
  References:
309
  ASHRAE Handbook—Fundamentals, Chapters 15 and 18.
310
  """
 
 
 
311
  if mode != "cooling" or component.component_type not in [ComponentType.WINDOW, ComponentType.SKYLIGHT]:
 
312
  return 0, None
313
 
314
  details = {} if return_details else None
@@ -346,10 +350,8 @@ class TFMCalculations:
346
  "diffuse_horizontal_radiation", "dry_bulb"]
347
  if not all(field in hourly_data for field in required_fields):
348
  logger.warning(f"Missing required fields in hourly_data for hour {hour}: {hourly_data}")
349
- return 0, details
350
-
351
- if hourly_data["global_horizontal_radiation"] <= 0:
352
- logger.info(f"No solar load for hour {hour} due to GHI={hourly_data['global_horizontal_radiation']}")
353
  return 0, details
354
 
355
  month = hourly_data["month"]
@@ -360,10 +362,6 @@ class TFMCalculations:
360
  dhi = hourly_data.get("diffuse_horizontal_radiation", ghi * 0.3)
361
  outdoor_temp = hourly_data["dry_bulb"]
362
 
363
- if ghi < 0 or dni < 0 or dhi < 0:
364
- logger.error(f"Negative radiation values for {month}/{day}/{hour}")
365
- raise ValueError(f"Negative radiation values for {month}/{day}/{hour}")
366
-
367
  if return_details:
368
  details["component"] = {
369
  "name": getattr(component, 'name', 'unknown'),
@@ -388,6 +386,16 @@ class TFMCalculations:
388
  "ground_reflectivity": ground_reflectivity
389
  }
390
 
 
 
 
 
 
 
 
 
 
 
391
  logger.info(f"Processing solar for {month}/{day}/{hour} with GHI={ghi}, DNI={dni}, DHI={dhi}, "
392
  f"dry_bulb={outdoor_temp}")
393
 
@@ -447,9 +455,9 @@ class TFMCalculations:
447
  shgc = glazing_material_obj.shgc
448
  h_o = glazing_material_obj.h_o
449
  else:
450
- logger.warning(f"Glazing material '{glazing_material.name}' not found for {component.id}. Using default SHGC=0.7.")
451
  else:
452
- logger.warning(f"No glazing material defined for {component.id}. Using default SHGC=0.7.")
453
 
454
  cos_theta = (math.sin(math.radians(alpha)) * math.cos(math.radians(surface_tilt)) +
455
  math.cos(math.radians(alpha)) * math.sin(math.radians(surface_tilt)) *
@@ -463,7 +471,7 @@ class TFMCalculations:
463
  "cos_incidence_angle": cos_theta
464
  }
465
 
466
- logger.info(f" Component {getattr(component, 'id', 'unknown_component')} at {month}/{day}/{hour}: "
467
  f"surface_tilt={surface_tilt:.2f}, surface_azimuth={surface_azimuth:.2f}, "
468
  f"cos_theta={cos_theta:.2f}")
469
 
@@ -489,15 +497,16 @@ class TFMCalculations:
489
  "solar_heat_gain_kw": solar_heat_gain
490
  }
491
 
492
- logger.info(f"Solar heat gain for {getattr(component, 'id', 'unknown_component')} at {month}/{day}/{hour}: "
493
  f"{solar_heat_gain:.2f} kW (area={component.area}, shgc_dynamic={shgc_dynamic:.2f}, "
494
  f"I_t={I_t:.2f}, iac={iac})")
495
 
496
  return solar_heat_gain, details
497
 
498
  except Exception as e:
499
- component_id = getattr(component, 'id', 'unknown_component')
500
  logger.error(f"Error calculating solar load for component {component_id} at hour {hour}: {str(e)}")
 
 
501
  return 0, details
502
 
503
  @staticmethod
@@ -666,10 +675,21 @@ class TFMCalculations:
666
  operating_periods = hvac_settings.get("operating_hours", [{"start": 8, "end": 18}])
667
  area = building_info.get("floor_area", 100.0)
668
 
 
 
 
 
 
 
 
669
  for comp_list in components.values():
670
  for comp in comp_list:
671
  comp.ctf = CTFCalculator.calculate_ctf_coefficients(comp)
672
 
 
 
 
 
673
  for idx, hour_data in enumerate(filtered_data):
674
  hour = hour_data["hour"]
675
  outdoor_temp = hour_data["dry_bulb"]
@@ -684,6 +704,10 @@ class TFMCalculations:
684
  is_operating = True
685
  break
686
  mode = "none" if abs(outdoor_temp - 18) < 0.01 else "cooling" if outdoor_temp > 18 else "heating"
 
 
 
 
687
  if is_operating and mode == "cooling":
688
  for comp_list in components.values():
689
  for comp in comp_list:
@@ -695,6 +719,7 @@ class TFMCalculations:
695
  solar += solar_load
696
  if idx == 0 and details:
697
  solar_details_first_hour.append(details)
 
698
  internal = TFMCalculations.calculate_internal_load(internal_loads, hour, max([p["end"] - p["start"] for p in operating_periods]), area)
699
  ventilation_cooling, _ = TFMCalculations.calculate_ventilation_load(internal_loads, outdoor_temp, indoor_temp, area, building_info, mode="cooling")
700
  infiltration_cooling, _ = TFMCalculations.calculate_infiltration_load(internal_loads, outdoor_temp, indoor_temp, area, building_info, mode="cooling")
@@ -746,6 +771,7 @@ class TFMCalculations:
746
  load["total_cooling"] = 0
747
  load["total_heating"] = 0
748
  final_loads.append(load)
 
749
  return {
750
  "loads": final_loads,
751
  "solar_details_first_hour": solar_details_first_hour
 
308
  References:
309
  ASHRAE Handbook—Fundamentals, Chapters 15 and 18.
310
  """
311
+ component_id = getattr(component, 'id', 'unknown_component')
312
+ logger.info(f"Processing solar load for component {component_id}, type: {component.component_type}, mode: {mode}, return_details: {return_details}")
313
+
314
  if mode != "cooling" or component.component_type not in [ComponentType.WINDOW, ComponentType.SKYLIGHT]:
315
+ logger.debug(f"Skipping solar load for {component_id}: mode={mode}, type={component.component_type}")
316
  return 0, None
317
 
318
  details = {} if return_details else None
 
350
  "diffuse_horizontal_radiation", "dry_bulb"]
351
  if not all(field in hourly_data for field in required_fields):
352
  logger.warning(f"Missing required fields in hourly_data for hour {hour}: {hourly_data}")
353
+ if return_details:
354
+ details["error"] = f"Missing required climate data fields: {required_fields}"
 
 
355
  return 0, details
356
 
357
  month = hourly_data["month"]
 
362
  dhi = hourly_data.get("diffuse_horizontal_radiation", ghi * 0.3)
363
  outdoor_temp = hourly_data["dry_bulb"]
364
 
 
 
 
 
365
  if return_details:
366
  details["component"] = {
367
  "name": getattr(component, 'name', 'unknown'),
 
386
  "ground_reflectivity": ground_reflectivity
387
  }
388
 
389
+ if ghi < 0 or dni < 0 or dhi < 0:
390
+ logger.error(f"Negative radiation values for {month}/{day}/{hour}")
391
+ if return_details:
392
+ details["error"] = "Negative radiation values"
393
+ return 0, details
394
+
395
+ if ghi <= 0:
396
+ logger.info(f"No solar load for {component_id} at hour {hour} due to GHI={ghi}")
397
+ return 0, details # Return details even if GHI is zero for first hour
398
+
399
  logger.info(f"Processing solar for {month}/{day}/{hour} with GHI={ghi}, DNI={dni}, DHI={dhi}, "
400
  f"dry_bulb={outdoor_temp}")
401
 
 
455
  shgc = glazing_material_obj.shgc
456
  h_o = glazing_material_obj.h_o
457
  else:
458
+ logger.warning(f"Glazing material '{glazing_material.name}' not found for {component_id}. Using default SHGC=0.7.")
459
  else:
460
+ logger.warning(f"No glazing material defined for {component_id}. Using default SHGC=0.7.")
461
 
462
  cos_theta = (math.sin(math.radians(alpha)) * math.cos(math.radians(surface_tilt)) +
463
  math.cos(math.radians(alpha)) * math.sin(math.radians(surface_tilt)) *
 
471
  "cos_incidence_angle": cos_theta
472
  }
473
 
474
+ logger.info(f" Component {component_id} at {month}/{day}/{hour}: "
475
  f"surface_tilt={surface_tilt:.2f}, surface_azimuth={surface_azimuth:.2f}, "
476
  f"cos_theta={cos_theta:.2f}")
477
 
 
497
  "solar_heat_gain_kw": solar_heat_gain
498
  }
499
 
500
+ logger.info(f"Solar heat gain for {component_id} at {month}/{day}/{hour}: "
501
  f"{solar_heat_gain:.2f} kW (area={component.area}, shgc_dynamic={shgc_dynamic:.2f}, "
502
  f"I_t={I_t:.2f}, iac={iac})")
503
 
504
  return solar_heat_gain, details
505
 
506
  except Exception as e:
 
507
  logger.error(f"Error calculating solar load for component {component_id} at hour {hour}: {str(e)}")
508
+ if return_details:
509
+ details["error"] = str(e)
510
  return 0, details
511
 
512
  @staticmethod
 
675
  operating_periods = hvac_settings.get("operating_hours", [{"start": 8, "end": 18}])
676
  area = building_info.get("floor_area", 100.0)
677
 
678
+ # Log available windows and skylights
679
+ windows = components.get("windows", [])
680
+ skylights = components.get("skylights", [])
681
+ logger.info(f"Windows defined: {len(windows)}, Skylights defined: {len(skylights)}")
682
+ for comp in windows + skylights:
683
+ logger.debug(f"Component: {comp.name}, Type: {comp.component_type}, Area: {comp.area}, SHGC: {comp.shgc}")
684
+
685
  for comp_list in components.values():
686
  for comp in comp_list:
687
  comp.ctf = CTFCalculator.calculate_ctf_coefficients(comp)
688
 
689
+ if not filtered_data:
690
+ logger.warning("No filtered hourly data available for simulation")
691
+ return {"loads": [], "solar_details_first_hour": []}
692
+
693
  for idx, hour_data in enumerate(filtered_data):
694
  hour = hour_data["hour"]
695
  outdoor_temp = hour_data["dry_bulb"]
 
704
  is_operating = True
705
  break
706
  mode = "none" if abs(outdoor_temp - 18) < 0.01 else "cooling" if outdoor_temp > 18 else "heating"
707
+ if idx == 0:
708
+ logger.info(f"First hour: {hour_data['month']}/{hour_data['day']}/{hour}, Outdoor Temp: {outdoor_temp}°C, Mode: {mode}, Operating: {is_operating}")
709
+ logger.debug(f"Climate data for first hour: {hour_data}")
710
+
711
  if is_operating and mode == "cooling":
712
  for comp_list in components.values():
713
  for comp in comp_list:
 
719
  solar += solar_load
720
  if idx == 0 and details:
721
  solar_details_first_hour.append(details)
722
+ logger.debug(f"Solar details for {comp.name}: {details}")
723
  internal = TFMCalculations.calculate_internal_load(internal_loads, hour, max([p["end"] - p["start"] for p in operating_periods]), area)
724
  ventilation_cooling, _ = TFMCalculations.calculate_ventilation_load(internal_loads, outdoor_temp, indoor_temp, area, building_info, mode="cooling")
725
  infiltration_cooling, _ = TFMCalculations.calculate_infiltration_load(internal_loads, outdoor_temp, indoor_temp, area, building_info, mode="cooling")
 
771
  load["total_cooling"] = 0
772
  load["total_heating"] = 0
773
  final_loads.append(load)
774
+ logger.info(f"Solar details collected for first hour: {len(solar_details_first_hour)} entries")
775
  return {
776
  "loads": final_loads,
777
  "solar_details_first_hour": solar_details_first_hour