mabuseif commited on
Commit
f51475f
·
verified ·
1 Parent(s): 2bac4bd

Update app/main.py

Browse files
Files changed (1) hide show
  1. app/main.py +92 -72
app/main.py CHANGED
@@ -3,6 +3,7 @@ HVAC Calculator Code Documentation.
3
  Updated 2025-05-02: Integrated skylights, surface color, glazing type, frame type, and drapery adjustments from main_new.py.
4
  Updated 2025-05-02: Enhanced per Plan.txt to include winter design temperature, humidity, building height, ventilation rate, internal load enhancements, and calculation parameters.
5
  Updated 2025-05-09: Fixed latitude parsing to return string (e.g., "24N") to match ASHRAE table keys and added group validation.
 
6
  """
7
 
8
  import streamlit as st
@@ -53,8 +54,8 @@ VENTILATION_RATES = {
53
  "Custom": {"people_rate": 0.0, "area_rate": 0.0}
54
  }
55
 
56
- # Valid wall and roof groups for ASHRAE CLTD tables (adjust based on ashrae_tables.py)
57
- VALID_WALL_GROUPS = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
58
  VALID_ROOF_GROUPS = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
59
 
60
  class HVACCalculator:
@@ -205,6 +206,18 @@ class HVACCalculator:
205
  if not self.climate_data.validate_climate_data(climate_data):
206
  return False, "Invalid climate data format or values."
207
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  # Validate components
209
  for component_type in ['walls', 'roofs', 'windows', 'doors', 'floors', 'skylights']:
210
  for comp in components.get(component_type, []):
@@ -303,11 +316,10 @@ class HVACCalculator:
303
  raise ValueError("Invalid latitude format")
304
 
305
  # Convert to ASHRAE table format (e.g., '24N', '32N')
306
- if lat_value in [24, 32, 40, 48]: # Common ASHRAE latitudes
 
307
  return f"{int(lat_value)}N"
308
  else:
309
- # Round to nearest supported latitude
310
- supported_latitudes = [24, 32, 40, 48]
311
  closest_lat = min(supported_latitudes, key=lambda x: abs(x - lat_value))
312
  st.warning(f"Latitude {lat_value} not in ASHRAE tables. Using closest: {closest_lat}N")
313
  return f"{closest_lat}N"
@@ -792,78 +804,86 @@ class HVACCalculator:
792
 
793
  # Populate detailed loads
794
  for wall in building_components.get('walls', []):
795
- load = self.cooling_calculator.calculate_wall_cooling_load(
796
- wall=wall,
797
- outdoor_temp=outdoor_conditions['temperature'],
798
- indoor_temp=indoor_conditions['temperature'],
799
- month=outdoor_conditions['month'],
800
- hour=design_loads['design_hour'],
801
- latitude=outdoor_conditions['latitude'],
802
- solar_absorptivity=wall.solar_absorptivity
803
- )
804
- if st.session_state.get('debug_mode', False):
805
- st.write("Debug: Wall CLTD Inputs", {
806
- 'wall_name': wall.name,
807
- 'element_type': 'wall',
808
- 'group': wall.wall_group,
809
- 'orientation': wall.orientation.value,
810
- 'hour': design_loads['design_hour'],
811
- 'latitude': self.parse_latitude(outdoor_conditions['latitude']),
812
- 'solar_absorptivity': wall.solar_absorptivity
813
- })
814
- results['detailed_loads']['walls'].append({
815
- 'name': wall.name,
816
- 'orientation': wall.orientation.value,
817
- 'area': wall.area,
818
- 'u_value': wall.u_value,
819
- 'solar_absorptivity': wall.solar_absorptivity,
820
- 'cltd': self.cooling_calculator.ashrae_tables.get_cltd(
821
- element_type='wall',
822
- group=wall.wall_group,
823
- orientation=wall.orientation.value,
824
  hour=design_loads['design_hour'],
825
- latitude=self.parse_latitude(outdoor_conditions['latitude']),
826
  solar_absorptivity=wall.solar_absorptivity
827
- ),
828
- 'load': load / 1000
829
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
830
 
831
  for roof in building_components.get('roofs', []):
832
- load = self.cooling_calculator.calculate_roof_cooling_load(
833
- roof=roof,
834
- outdoor_temp=outdoor_conditions['temperature'],
835
- indoor_temp=indoor_conditions['temperature'],
836
- month=outdoor_conditions['month'],
837
- hour=design_loads['design_hour'],
838
- latitude=outdoor_conditions['latitude'],
839
- solar_absorptivity=roof.solar_absorptivity
840
- )
841
- if st.session_state.get('debug_mode', False):
842
- st.write("Debug: Roof CLTD Inputs", {
843
- 'roof_name': roof.name,
844
- 'element_type': 'roof',
845
- 'group': roof.roof_group,
846
- 'orientation': roof.orientation.value,
847
- 'hour': design_loads['design_hour'],
848
- 'latitude': self.parse_latitude(outdoor_conditions['latitude']),
849
- 'solar_absorptivity': roof.solar_absorptivity
850
- })
851
- results['detailed_loads']['roofs'].append({
852
- 'name': roof.name,
853
- 'orientation': roof.orientation.value,
854
- 'area': roof.area,
855
- 'u_value': roof.u_value,
856
- 'solar_absorptivity': roof.solar_absorptivity,
857
- 'cltd': self.cooling_calculator.ashrae_tables.get_cltd(
858
- element_type='roof',
859
- group=roof.roof_group,
860
- orientation=roof.orientation.value,
861
  hour=design_loads['design_hour'],
862
- latitude=self.parse_latitude(outdoor_conditions['latitude']),
863
  solar_absorptivity=roof.solar_absorptivity
864
- ),
865
- 'load': load / 1000
866
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
867
 
868
  for window in building_components.get('windows', []):
869
  adjusted_shgc = self.drapery.adjust_shgc(
@@ -1272,7 +1292,7 @@ class HVACCalculator:
1272
  results['detailed_loads']['floors'].append({
1273
  'name': floor.name,
1274
  'area': floor.area,
1275
- 'u_value': floor.area, # CHANGED: Fixed typo (u_value was incorrectly set to area)
1276
  'delta_t': indoor_conditions['temperature'] - outdoor_conditions['ground_temperature'],
1277
  'load': load / 1000
1278
  })
 
3
  Updated 2025-05-02: Integrated skylights, surface color, glazing type, frame type, and drapery adjustments from main_new.py.
4
  Updated 2025-05-02: Enhanced per Plan.txt to include winter design temperature, humidity, building height, ventilation rate, internal load enhancements, and calculation parameters.
5
  Updated 2025-05-09: Fixed latitude parsing to return string (e.g., "24N") to match ASHRAE table keys and added group validation.
6
+ Updated 2025-05-09: Corrected group validation to use alphabetical groups (A, B, C, ...) and enhanced stale component handling.
7
  """
8
 
9
  import streamlit as st
 
54
  "Custom": {"people_rate": 0.0, "area_rate": 0.0}
55
  }
56
 
57
+ # Valid wall and roof groups for ASHRAE CLTD tables (alphabetical, based on ASHRAE tables)
58
+ VALID_WALL_GROUPS = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
59
  VALID_ROOF_GROUPS = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
60
 
61
  class HVACCalculator:
 
206
  if not self.climate_data.validate_climate_data(climate_data):
207
  return False, "Invalid climate data format or values."
208
 
209
+ # Fix stale components with invalid groups
210
+ for component_type in ['walls', 'roofs']:
211
+ for comp in components.get(component_type, []):
212
+ if component_type == 'walls':
213
+ if getattr(comp, 'wall_group', '') not in VALID_WALL_GROUPS:
214
+ st.warning(f"Invalid wall group '{comp.wall_group}' for {comp.name}. Setting to 'A'.")
215
+ comp.wall_group = 'A'
216
+ if component_type == 'roofs':
217
+ if getattr(comp, 'roof_group', '') not in VALID_ROOF_GROUPS:
218
+ st.warning(f"Invalid roof group '{comp.roof_group}' for {comp.name}. Setting to 'A'.")
219
+ comp.roof_group = 'A'
220
+
221
  # Validate components
222
  for component_type in ['walls', 'roofs', 'windows', 'doors', 'floors', 'skylights']:
223
  for comp in components.get(component_type, []):
 
316
  raise ValueError("Invalid latitude format")
317
 
318
  # Convert to ASHRAE table format (e.g., '24N', '32N')
319
+ supported_latitudes = [24, 32, 40, 48]
320
+ if lat_value in supported_latitudes:
321
  return f"{int(lat_value)}N"
322
  else:
 
 
323
  closest_lat = min(supported_latitudes, key=lambda x: abs(x - lat_value))
324
  st.warning(f"Latitude {lat_value} not in ASHRAE tables. Using closest: {closest_lat}N")
325
  return f"{closest_lat}N"
 
804
 
805
  # Populate detailed loads
806
  for wall in building_components.get('walls', []):
807
+ try:
808
+ load = self.cooling_calculator.calculate_wall_cooling_load(
809
+ wall=wall,
810
+ outdoor_temp=outdoor_conditions['temperature'],
811
+ indoor_temp=indoor_conditions['temperature'],
812
+ month=outdoor_conditions['month'],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
813
  hour=design_loads['design_hour'],
814
+ latitude=outdoor_conditions['latitude'],
815
  solar_absorptivity=wall.solar_absorptivity
816
+ )
817
+ if st.session_state.get('debug_mode', False):
818
+ st.write("Debug: Wall CLTD Inputs", {
819
+ 'wall_name': wall.name,
820
+ 'element_type': 'wall',
821
+ 'group': wall.wall_group,
822
+ 'orientation': wall.orientation.value,
823
+ 'hour': design_loads['design_hour'],
824
+ 'latitude': self.parse_latitude(outdoor_conditions['latitude']),
825
+ 'solar_absorptivity': wall.solar_absorptivity
826
+ })
827
+ results['detailed_loads']['walls'].append({
828
+ 'name': wall.name,
829
+ 'orientation': wall.orientation.value,
830
+ 'area': wall.area,
831
+ 'u_value': wall.u_value,
832
+ 'solar_absorptivity': wall.solar_absorptivity,
833
+ 'cltd': self.cooling_calculator.ashrae_tables.get_cltd(
834
+ element_type='wall',
835
+ group=wall.wall_group,
836
+ orientation=wall.orientation.value,
837
+ hour=design_loads['design_hour'],
838
+ latitude=self.parse_latitude(outdoor_conditions['latitude']),
839
+ solar_absorptivity=wall.solar_absorptivity
840
+ ),
841
+ 'load': load / 1000
842
+ })
843
+ except TypeError as te:
844
+ st.error(f"Type error in wall CLTD calculation for {wall.name}: {str(te)}")
845
+ return False, f"Type error in wall CLTD calculation: {str(te)}", {}
846
 
847
  for roof in building_components.get('roofs', []):
848
+ try:
849
+ load = self.cooling_calculator.calculate_roof_cooling_load(
850
+ roof=roof,
851
+ outdoor_temp=outdoor_conditions['temperature'],
852
+ indoor_temp=indoor_conditions['temperature'],
853
+ month=outdoor_conditions['month'],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
854
  hour=design_loads['design_hour'],
855
+ latitude=outdoor_conditions['latitude'],
856
  solar_absorptivity=roof.solar_absorptivity
857
+ )
858
+ if st.session_state.get('debug_mode', False):
859
+ st.write("Debug: Roof CLTD Inputs", {
860
+ 'roof_name': roof.name,
861
+ 'element_type': 'roof',
862
+ 'group': roof.roof_group,
863
+ 'orientation': roof.orientation.value,
864
+ 'hour': design_loads['design_hour'],
865
+ 'latitude': self.parse_latitude(outdoor_conditions['latitude']),
866
+ 'solar_absorptivity': roof.solar_absorptivity
867
+ })
868
+ results['detailed_loads']['roofs'].append({
869
+ 'name': roof.name,
870
+ 'orientation': roof.orientation.value,
871
+ 'area': roof.area,
872
+ 'u_value': roof.u_value,
873
+ 'solar_absorptivity': roof.solar_absorptivity,
874
+ 'cltd': self.cooling_calculator.ashrae_tables.get_cltd(
875
+ element_type='roof',
876
+ group=roof.roof_group,
877
+ orientation=roof.orientation.value,
878
+ hour=design_loads['design_hour'],
879
+ latitude=self.parse_latitude(outdoor_conditions['latitude']),
880
+ solar_absorptivity=roof.solar_absorptivity
881
+ ),
882
+ 'load': load / 1000
883
+ })
884
+ except TypeError as te:
885
+ st.error(f"Type error in roof CLTD calculation for {roof.name}: {str(te)}")
886
+ return False, f"Type error in roof CLTD calculation: {str(te)}", {}
887
 
888
  for window in building_components.get('windows', []):
889
  adjusted_shgc = self.drapery.adjust_shgc(
 
1292
  results['detailed_loads']['floors'].append({
1293
  'name': floor.name,
1294
  'area': floor.area,
1295
+ 'u_value': floor.u_value, # FIXED: Corrected typo from previous version
1296
  'delta_t': indoor_conditions['temperature'] - outdoor_conditions['ground_temperature'],
1297
  'load': load / 1000
1298
  })