Spaces:
Sleeping
Sleeping
Update app/hvac_loads.py
Browse files- app/hvac_loads.py +25 -79
app/hvac_loads.py
CHANGED
@@ -181,94 +181,40 @@ class TFMCalculations:
|
|
181 |
component_name = component.get('name', 'unnamed_component')
|
182 |
component_type = TFMCalculations.get_component_type(component)
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
|
|
|
|
189 |
|
190 |
try:
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
surface_azimuth = component.get('orientation', 0.0)
|
195 |
-
logger.debug(f"Roof component {component_name}: using orientation={surface_azimuth}, tilt={surface_tilt}")
|
196 |
-
|
197 |
-
elif component_type == ComponentType.SKYLIGHT:
|
198 |
-
surface_tilt = component.get('tilt', 0.0)
|
199 |
-
h_o = 23.0
|
200 |
-
surface_azimuth = component.get('orientation', 0.0)
|
201 |
-
logger.debug(f"Skylight component {component_name}: using orientation={surface_azimuth}, tilt={surface_tilt}")
|
202 |
-
|
203 |
-
elif component_type == ComponentType.FLOOR:
|
204 |
-
surface_tilt = 180.0
|
205 |
-
h_o = 17.0
|
206 |
-
surface_azimuth = 0.0
|
207 |
-
logger.debug(f"Floor component {component_name}: using default azimuth={surface_azimuth}, tilt={surface_tilt}")
|
208 |
-
|
209 |
-
else: # WALL, WINDOW
|
210 |
-
surface_tilt = 90.0
|
211 |
-
h_o = 17.0
|
212 |
-
elevation = component.get('elevation', None)
|
213 |
-
if not elevation:
|
214 |
-
logger.warning(f"Component {component_name} ({component_type.value}) is missing 'elevation' field. Using default azimuth=0.")
|
215 |
-
surface_azimuth = 0.0
|
216 |
-
else:
|
217 |
-
base_azimuth = building_info.get("orientation_angle", 0.0)
|
218 |
-
elevation_angles = {
|
219 |
-
"A": base_azimuth,
|
220 |
-
"B": (base_azimuth + 90.0) % 360,
|
221 |
-
"C": (base_azimuth + 180.0) % 360,
|
222 |
-
"D": (base_azimuth + 270.0) % 360
|
223 |
-
}
|
224 |
-
if elevation not in elevation_angles:
|
225 |
-
logger.warning(f"Invalid elevation '{elevation}' for {component_name}. Using default azimuth=0.")
|
226 |
-
surface_azimuth = 0.0
|
227 |
-
else:
|
228 |
-
surface_azimuth = (elevation_angles[elevation] + component.get('rotation', 0.0)) % 360
|
229 |
-
logger.debug(f"Component {component_name}: elevation={elevation}, base_azimuth={elevation_angles[elevation]}, rotation={component.get('rotation', 0.0)}, total_azimuth={surface_azimuth}")
|
230 |
-
|
231 |
-
if component_type in [ComponentType.WALL, ComponentType.ROOF]:
|
232 |
-
construction_name = component.get('construction', None)
|
233 |
-
if not construction_name:
|
234 |
-
logger.warning(f"No construction defined for {component_name}. Using defaults: absorptivity=0.6, emissivity=0.9.")
|
235 |
-
else:
|
236 |
-
construction_obj = (project_constructions.get(construction_name) or
|
237 |
-
material_library.library_constructions.get(construction_name))
|
238 |
-
if not construction_obj:
|
239 |
-
logger.warning(f"Construction '{construction_name}' not found for {component_name}. Using defaults: absorptivity=0.6, emissivity=0.9.")
|
240 |
-
elif not construction_obj.get('layers', []):
|
241 |
-
logger.warning(f"No layers in construction for {component_name}. Using defaults: absorptivity=0.6, emissivity=0.9.")
|
242 |
-
else:
|
243 |
-
first_layer = construction_obj['layers'][0]
|
244 |
-
material_name = first_layer.get("material")
|
245 |
-
if material_name:
|
246 |
-
material_obj = (project_materials.get(material_name) or
|
247 |
-
material_library.library_materials.get(material_name))
|
248 |
-
if material_obj:
|
249 |
-
absorptivity = material_obj.get('absorptivity', 0.6)
|
250 |
-
emissivity = material_obj.get('emissivity', 0.9)
|
251 |
-
logger.debug(f"Using first layer material '{material_name}' for {component_name}: absorptivity={absorptivity}, emissivity={emissivity}")
|
252 |
-
|
253 |
-
elif component_type in [ComponentType.WINDOW, ComponentType.SKYLIGHT]:
|
254 |
-
glazing_material_name = component.get('glazing_material', None)
|
255 |
if not glazing_material_name:
|
256 |
-
logger.warning(f"No
|
257 |
-
|
258 |
else:
|
259 |
glazing_material_obj = (project_glazing_materials.get(glazing_material_name) or
|
260 |
material_library.library_glazing_materials.get(glazing_material_name))
|
261 |
if not glazing_material_obj:
|
262 |
-
logger.warning(f"
|
263 |
-
|
264 |
else:
|
265 |
-
|
266 |
h_o = glazing_material_obj.get('h_o', h_o)
|
267 |
-
logger.debug(f"Using
|
268 |
-
emissivity = None
|
|
|
|
|
|
|
|
|
269 |
|
270 |
except Exception as e:
|
271 |
logger.error(f"Error retrieving surface parameters for {component_name}: {str(e)}")
|
|
|
272 |
if component_type == ComponentType.ROOF:
|
273 |
surface_tilt = 0.0
|
274 |
h_o = 23.0
|
@@ -290,11 +236,11 @@ class TFMCalculations:
|
|
290 |
absorptivity = 0.6
|
291 |
emissivity = 0.9
|
292 |
else: # WINDOW, SKYLIGHT
|
293 |
-
|
294 |
emissivity = None
|
295 |
|
296 |
-
|
297 |
-
|
298 |
|
299 |
@staticmethod
|
300 |
def calculate_solar_load(component: Dict[str, Any], hourly_data: Dict, hour: int, building_orientation: float, mode: str = "none") -> float:
|
|
|
181 |
component_name = component.get('name', 'unnamed_component')
|
182 |
component_type = TFMCalculations.get_component_type(component)
|
183 |
|
184 |
+
# Default parameters
|
185 |
+
surface_tilt = component.get('surface_tilt', 90.0 if component_type in [ComponentType.WALL, ComponentType.WINDOW] else
|
186 |
+
0.0 if component_type in [ComponentType.ROOF, ComponentType.SKYLIGHT] else 180.0)
|
187 |
+
surface_azimuth = component.get('surface_azimuth', 0.0)
|
188 |
+
h_o = 17.0 if component_type in [ComponentType.WALL, ComponentType.WINDOW, ComponentType.FLOOR] else 23.0
|
189 |
+
emissivity = component.get('emissivity', 0.9 if component_type in [ComponentType.WALL, ComponentType.ROOF] else None)
|
190 |
+
absorptivity = component.get('absorptivity', 0.6 if component_type in [ComponentType.WALL, ComponentType.ROOF] else 0.0)
|
191 |
|
192 |
try:
|
193 |
+
# For windows and skylights, adjust h_o and use shgc instead of absorptivity
|
194 |
+
if component_type in [ComponentType.WINDOW, ComponentType.SKYLIGHT]:
|
195 |
+
glazing_material_name = component.get('fenestration', None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
if not glazing_material_name:
|
197 |
+
logger.warning(f"No fenestration defined for {component_name}. Using default SHGC=0.7, h_o={h_o}.")
|
198 |
+
absorptivity = component.get('shgc', 0.7) # Use shgc as absorptivity for consistency
|
199 |
else:
|
200 |
glazing_material_obj = (project_glazing_materials.get(glazing_material_name) or
|
201 |
material_library.library_glazing_materials.get(glazing_material_name))
|
202 |
if not glazing_material_obj:
|
203 |
+
logger.warning(f"Fenestration '{glazing_material_name}' not found for {component_name}. Using default SHGC=0.7, h_o={h_o}.")
|
204 |
+
absorptivity = component.get('shgc', 0.7)
|
205 |
else:
|
206 |
+
absorptivity = glazing_material_obj.get('shgc', component.get('shgc', 0.7))
|
207 |
h_o = glazing_material_obj.get('h_o', h_o)
|
208 |
+
logger.debug(f"Using fenestration '{glazing_material_name}' for {component_name}: shgc={absorptivity}, h_o={h_o}")
|
209 |
+
emissivity = None # Emissivity not used for fenestrations
|
210 |
+
|
211 |
+
logger.info(f"Surface parameters for {component_name}: tilt={surface_tilt:.1f}, azimuth={surface_azimuth:.1f}, h_o={h_o:.1f}, "
|
212 |
+
f"emissivity={emissivity}, absorptivity={absorptivity}")
|
213 |
+
return surface_tilt, surface_azimuth, h_o, emissivity, absorptivity
|
214 |
|
215 |
except Exception as e:
|
216 |
logger.error(f"Error retrieving surface parameters for {component_name}: {str(e)}")
|
217 |
+
# Apply defaults on error
|
218 |
if component_type == ComponentType.ROOF:
|
219 |
surface_tilt = 0.0
|
220 |
h_o = 23.0
|
|
|
236 |
absorptivity = 0.6
|
237 |
emissivity = 0.9
|
238 |
else: # WINDOW, SKYLIGHT
|
239 |
+
absorptivity = 0.7
|
240 |
emissivity = None
|
241 |
|
242 |
+
logger.info(f"Default surface parameters for {component_name}: tilt={surface_tilt:.1f}, azimuth={surface_azimuth:.1f}, h_o={h_o:.1f}")
|
243 |
+
return surface_tilt, surface_azimuth, h_o, emissivity, absorptivity
|
244 |
|
245 |
@staticmethod
|
246 |
def calculate_solar_load(component: Dict[str, Any], hourly_data: Dict, hour: int, building_orientation: float, mode: str = "none") -> float:
|