mabuseif commited on
Commit
4f7c430
·
verified ·
1 Parent(s): ee8c13b

Update utils/solar.py

Browse files
Files changed (1) hide show
  1. utils/solar.py +24 -38
utils/solar.py CHANGED
@@ -4,6 +4,7 @@ import math
4
  from datetime import datetime
5
  from app.materials_library import MaterialLibrary, GlazingMaterial, Material
6
  from utils.ctf_calculations import ComponentType
 
7
  import logging
8
 
9
  # Configure logging
@@ -118,8 +119,8 @@ class SolarCalculations:
118
  Tuple[float, float, float, Optional[float], float]: Surface tilt (°), surface azimuth (°),
119
  h_o (W/m²·K), emissivity, absorptivity.
120
  """
121
- component_id = component.get('id', 'unknown_component')
122
- component_type = component.get('type', 'wall').lower() # Changed to dictionary access
123
 
124
  # Map string type to ComponentType enum
125
  type_map = {
@@ -142,44 +143,36 @@ class SolarCalculations:
142
  h_o = 23.0
143
  elif component_type == ComponentType.SKYLIGHT:
144
  surface_tilt = component.get('surface_tilt', 0.0)
145
- h_o = 23.0
146
  elif component_type == ComponentType.FLOOR:
147
  surface_tilt = component.get('surface_tilt', 180.0)
148
  h_o = 17.0
149
  else: # WALL, WINDOW
150
  surface_tilt = component.get('surface_tilt', 90.0)
151
- h_o = 17.0
152
 
153
  surface_azimuth = component.get('surface_azimuth', 0.0)
154
  emissivity = component.get('emissivity', 0.9 if component_type in [ComponentType.WALL, ComponentType.ROOF] else None)
155
  absorptivity = component.get('absorptivity', 0.6 if component_type in [ComponentType.WALL, ComponentType.ROOF] else 0.0)
156
 
157
  try:
158
- # For windows and skylights, use shgc instead of absorptivity and adjust h_o
159
  if component_type in [ComponentType.WINDOW, ComponentType.SKYLIGHT]:
160
- fenestration_name = component.get('fenestration', None) # Standardized to 'fenestration'
161
  if not fenestration_name:
162
- logger.warning(f"No fenestration defined for {component_id}. Using default SHGC=0.7, h_o={h_o}.")
163
  absorptivity = component.get('shgc', 0.7)
164
  else:
165
- glazing_material_obj = (self.project_glazing_materials.get(fenestration_name) or
166
- self.material_library.library_glazing_materials.get(fenestration_name))
167
- if not glazing_material_obj:
168
- logger.warning(f"Fenestration '{fenestration_name}' not found for {component_id}. Using default SHGC=0.7, h_o={h_o}.")
169
- absorptivity = component.get('shgc', 0.7)
170
- else:
171
- absorptivity = glazing_material_obj.get('shgc', component.get('shgc', 0.7))
172
- h_o = glazing_material_obj.get('h_o', h_o)
173
- logger.debug(f"Using fenestration '{fenestration_name}' for {component_id}: shgc={absorptivity}, h_o={h_o}")
174
- emissivity = None
175
 
176
- logger.debug(f"Surface parameters for {component_id}: tilt={surface_tilt:.2f}, azimuth={surface_azimuth:.2f}, "
177
  f"h_o={h_o:.2f}, emissivity={emissivity}, absorptivity={absorptivity}")
178
 
179
  return surface_tilt, surface_azimuth, h_o, emissivity, absorptivity
180
 
181
  except Exception as e:
182
- logger.error(f"Error retrieving surface parameters for {component_id}: {str(e)}")
183
  # Apply defaults
184
  if component_type == ComponentType.ROOF:
185
  surface_tilt = 0.0
@@ -187,7 +180,7 @@ class SolarCalculations:
187
  surface_azimuth = 0.0
188
  elif component_type == ComponentType.SKYLIGHT:
189
  surface_tilt = 0.0
190
- h_o = 23.0
191
  surface_azimuth = 0.0
192
  elif component_type == ComponentType.FLOOR:
193
  surface_tilt = 180.0
@@ -195,7 +188,7 @@ class SolarCalculations:
195
  surface_azimuth = 0.0
196
  else: # WALL, WINDOW
197
  surface_tilt = 90.0
198
- h_o = 17.0
199
  surface_azimuth = 0.0
200
 
201
  if component_type in [ComponentType.WALL, ComponentType.ROOF]:
@@ -205,7 +198,7 @@ class SolarCalculations:
205
  absorptivity = 0.7
206
  emissivity = None
207
 
208
- logger.info(f"Default surface parameters for {component_id}: tilt={surface_tilt:.1f}, azimuth={surface_azimuth:.1f}, h_o={h_o:.1f}")
209
  return surface_tilt, surface_azimuth, h_o, emissivity, absorptivity
210
 
211
  @staticmethod
@@ -361,15 +354,8 @@ class SolarCalculations:
361
  self.get_surface_parameters(comp, building_info)
362
 
363
  # For windows/skylights, get SHGC from component
364
- shgc = comp.get('shgc', 0.7) # Changed to dictionary access
365
- fenestration_name = comp.get('fenestration', None) # Standardized to 'fenestration'
366
- if fenestration_name:
367
- glazing_material_obj = (self.project_glazing_materials.get(fenestration_name) or
368
- self.material_library.library_glazing_materials.get(fenestration_name))
369
- if glazing_material_obj:
370
- shgc = glazing_material_obj.get('shgc', shgc)
371
- else:
372
- logger.warning(f"Fenestration '{fenestration_name}' not found for {comp.get('id', 'unknown_component')}. Using default SHGC={shgc}.")
373
 
374
  # Calculate angle of incidence (θ)
375
  cos_theta = (math.sin(math.radians(alpha)) * math.cos(math.radians(surface_tilt)) +
@@ -377,8 +363,8 @@ class SolarCalculations:
377
  math.cos(math.radians(azimuth - surface_azimuth)))
378
  cos_theta = max(min(cos_theta, 1.0), 0.0) # Clamp to [0, 1]
379
 
380
- logger.info(f" Component {comp.get('id', 'unknown_component')} at {month}/{day}/{hour}: "
381
- f"surface_tilt={surface_tilt:.2f}, surface_azimuth={surface_azimuth:.2f}, " # Fixed typo
382
  f"cos_theta={cos_theta:.2f}")
383
 
384
  # Calculate total incident radiation (I_t)
@@ -388,7 +374,7 @@ class SolarCalculations:
388
 
389
  # Initialize result
390
  comp_result = {
391
- "component_id": comp.get('id', 'unknown_component'),
392
  "total_incident_radiation": round(I_t, 2),
393
  "absorptivity": round(absorptivity, 2),
394
  "emissivity": round(emissivity, 2) if emissivity is not None else None
@@ -404,8 +390,8 @@ class SolarCalculations:
404
 
405
  # Calculate solar heat gain for fenestration
406
  elif comp.get('type', '').lower() in ['windows', 'skylights']:
407
- glazing_type = self.GLAZING_TYPE_MAPPING.get(comp.get('name', ''), 'Single Clear')
408
- iac = comp.get('shading_coefficient', 1.0) # Changed to dictionary access, aligned with components.py
409
  shgc_dynamic = shgc * self.calculate_dynamic_shgc(glazing_type, cos_theta)
410
  solar_heat_gain = comp.get('area', 0.0) * shgc_dynamic * I_t * iac / 1000 # kW
411
  comp_result["solar_heat_gain"] = round(solar_heat_gain, 2)
@@ -417,8 +403,8 @@ class SolarCalculations:
417
  component_results.append(comp_result)
418
 
419
  except Exception as e:
420
- component_id = comp.get('id', 'unknown_component')
421
- logger.error(f"Error processing component {component_id} at {month}/{day}/{hour}: {str(e)}")
422
  continue
423
 
424
  # Store results for this hour
 
4
  from datetime import datetime
5
  from app.materials_library import MaterialLibrary, GlazingMaterial, Material
6
  from utils.ctf_calculations import ComponentType
7
+ from app.m_c_data import DEFAULT_WINDOW_PROPERTIES # Import for h_o default
8
  import logging
9
 
10
  # Configure logging
 
119
  Tuple[float, float, float, Optional[float], float]: Surface tilt (°), surface azimuth (°),
120
  h_o (W/m²·K), emissivity, absorptivity.
121
  """
122
+ component_name = component.get('name', 'unknown_component')
123
+ component_type = component.get('type', 'wall').lower()
124
 
125
  # Map string type to ComponentType enum
126
  type_map = {
 
143
  h_o = 23.0
144
  elif component_type == ComponentType.SKYLIGHT:
145
  surface_tilt = component.get('surface_tilt', 0.0)
146
+ h_o = component.get('h_o', DEFAULT_WINDOW_PROPERTIES["h_o"])
147
  elif component_type == ComponentType.FLOOR:
148
  surface_tilt = component.get('surface_tilt', 180.0)
149
  h_o = 17.0
150
  else: # WALL, WINDOW
151
  surface_tilt = component.get('surface_tilt', 90.0)
152
+ h_o = component.get('h_o', DEFAULT_WINDOW_PROPERTIES["h_o"]) if component_type == ComponentType.WINDOW else 17.0
153
 
154
  surface_azimuth = component.get('surface_azimuth', 0.0)
155
  emissivity = component.get('emissivity', 0.9 if component_type in [ComponentType.WALL, ComponentType.ROOF] else None)
156
  absorptivity = component.get('absorptivity', 0.6 if component_type in [ComponentType.WALL, ComponentType.ROOF] else 0.0)
157
 
158
  try:
159
+ # For windows and skylights, use shgc instead of absorptivity
160
  if component_type in [ComponentType.WINDOW, ComponentType.SKYLIGHT]:
161
+ fenestration_name = component.get('fenestration', None)
162
  if not fenestration_name:
163
+ logger.warning(f"No fenestration defined for {component_name}. Using default SHGC=0.7, h_o={h_o}.")
164
  absorptivity = component.get('shgc', 0.7)
165
  else:
166
+ absorptivity = component.get('shgc', 0.7)
167
+ logger.debug(f"Using component-stored SHGC for {component_name}: shgc={absorptivity}, h_o={h_o}")
 
 
 
 
 
 
 
 
168
 
169
+ logger.debug(f"Surface parameters for {component_name}: tilt={surface_tilt:.2f}, azimuth={surface_azimuth:.2f}, "
170
  f"h_o={h_o:.2f}, emissivity={emissivity}, absorptivity={absorptivity}")
171
 
172
  return surface_tilt, surface_azimuth, h_o, emissivity, absorptivity
173
 
174
  except Exception as e:
175
+ logger.error(f"Error retrieving surface parameters for {component_name}: {str(e)}")
176
  # Apply defaults
177
  if component_type == ComponentType.ROOF:
178
  surface_tilt = 0.0
 
180
  surface_azimuth = 0.0
181
  elif component_type == ComponentType.SKYLIGHT:
182
  surface_tilt = 0.0
183
+ h_o = DEFAULT_WINDOW_PROPERTIES["h_o"]
184
  surface_azimuth = 0.0
185
  elif component_type == ComponentType.FLOOR:
186
  surface_tilt = 180.0
 
188
  surface_azimuth = 0.0
189
  else: # WALL, WINDOW
190
  surface_tilt = 90.0
191
+ h_o = DEFAULT_WINDOW_PROPERTIES["h_o"] if component_type == ComponentType.WINDOW else 17.0
192
  surface_azimuth = 0.0
193
 
194
  if component_type in [ComponentType.WALL, ComponentType.ROOF]:
 
198
  absorptivity = 0.7
199
  emissivity = None
200
 
201
+ logger.info(f"Default surface parameters for {component_name}: tilt={surface_tilt:.1f}, azimuth={surface_azimuth:.1f}, h_o={h_o:.1f}")
202
  return surface_tilt, surface_azimuth, h_o, emissivity, absorptivity
203
 
204
  @staticmethod
 
354
  self.get_surface_parameters(comp, building_info)
355
 
356
  # For windows/skylights, get SHGC from component
357
+ shgc = comp.get('shgc', 0.7)
358
+ fenestration_name = comp.get('fenestration', None)
 
 
 
 
 
 
 
359
 
360
  # Calculate angle of incidence (θ)
361
  cos_theta = (math.sin(math.radians(alpha)) * math.cos(math.radians(surface_tilt)) +
 
363
  math.cos(math.radians(azimuth - surface_azimuth)))
364
  cos_theta = max(min(cos_theta, 1.0), 0.0) # Clamp to [0, 1]
365
 
366
+ logger.info(f" Component {comp.get('name', 'unknown_component')} at {month}/{day}/{hour}: "
367
+ f"surface_tilt={surface_tilt:.2f}, surface_azimuth={surface_azimuth:.2f}, "
368
  f"cos_theta={cos_theta:.2f}")
369
 
370
  # Calculate total incident radiation (I_t)
 
374
 
375
  # Initialize result
376
  comp_result = {
377
+ "component_id": comp.get('name', 'unknown_component'),
378
  "total_incident_radiation": round(I_t, 2),
379
  "absorptivity": round(absorptivity, 2),
380
  "emissivity": round(emissivity, 2) if emissivity is not None else None
 
390
 
391
  # Calculate solar heat gain for fenestration
392
  elif comp.get('type', '').lower() in ['windows', 'skylights']:
393
+ glazing_type = self.GLAZING_TYPE_MAPPING.get(comp.get('fenestration', ''), 'Single Clear')
394
+ iac = comp.get('shading_coefficient', 1.0)
395
  shgc_dynamic = shgc * self.calculate_dynamic_shgc(glazing_type, cos_theta)
396
  solar_heat_gain = comp.get('area', 0.0) * shgc_dynamic * I_t * iac / 1000 # kW
397
  comp_result["solar_heat_gain"] = round(solar_heat_gain, 2)
 
403
  component_results.append(comp_result)
404
 
405
  except Exception as e:
406
+ component_name = comp.get('name', 'unknown_component')
407
+ logger.error(f"Error processing component {component_name} at {month}/{day}/{hour}: {str(e)}")
408
  continue
409
 
410
  # Store results for this hour