mabuseif commited on
Commit
ff8b3af
·
verified ·
1 Parent(s): cc8b950

Update utils/ctf_calculations.py

Browse files
Files changed (1) hide show
  1. utils/ctf_calculations.py +88 -1
utils/ctf_calculations.py CHANGED
@@ -17,6 +17,7 @@ import threading
17
  from typing import List, Dict, Any, NamedTuple
18
  import streamlit as st
19
  from enum import Enum
 
20
 
21
  # Configure logging
22
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
@@ -310,4 +311,90 @@ class CTFCalculator:
310
  CTFCoefficients: Placeholder zero coefficients until implementation.
311
  """
312
  logger.info(f"CTF table calculation for {component.get('type', 'Unknown')} component '{component.get('name', 'Unknown')}' not yet implemented. Returning zero coefficients.")
313
- return CTFCoefficients(X=[0.0], Y=[0.0], Z=[0.0], F=[0.0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  from typing import List, Dict, Any, NamedTuple
18
  import streamlit as st
19
  from enum import Enum
20
+ from utils.solar import SolarCalculations
21
 
22
  # Configure logging
23
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 
311
  CTFCoefficients: Placeholder zero coefficients until implementation.
312
  """
313
  logger.info(f"CTF table calculation for {component.get('type', 'Unknown')} component '{component.get('name', 'Unknown')}' not yet implemented. Returning zero coefficients.")
314
+ return CTFCoefficients(X=[0.0], Y=[0.0], Z=[0.0], F=[0.0])
315
+
316
+ @classmethod
317
+ def calculate_heat_flux(cls, component: Dict[str, Any], hourly_data: Dict[str, Any],
318
+ solar_calc: SolarCalculations, building_info: Dict[str, Any]) -> float:
319
+ """Calculate hourly heat flux using CTF coefficients and sol-air temperature.
320
+
321
+ Args:
322
+ component: Dictionary containing component properties.
323
+ hourly_data: Dictionary with month, day, hour, dry_bulb, dew_point, wind_speed,
324
+ total_sky_cover, global_horizontal_radiation, direct_normal_radiation,
325
+ diffuse_horizontal_radiation.
326
+ solar_calc: SolarCalculations instance for sol-air temperature.
327
+ building_info: Building information dictionary.
328
+
329
+ Returns:
330
+ float: Heat flux through the component (W/m²).
331
+
332
+ References:
333
+ ASHRAE Handbook—Fundamentals, Chapter 26.
334
+ """
335
+ # Get component type
336
+ comp_type_str = component.get('type', '').lower()
337
+ comp_type_map = {
338
+ 'walls': ComponentType.WALL,
339
+ 'roofs': ComponentType.ROOF,
340
+ 'floors': ComponentType.FLOOR,
341
+ 'windows': ComponentType.WINDOW,
342
+ 'skylights': ComponentType.SKYLIGHT
343
+ }
344
+ component_type = comp_type_map.get(comp_type_str, None)
345
+ if not component_type:
346
+ logger.warning(f"Invalid component type '{comp_type_str}' for component '{component.get('name', 'Unknown')}'. Returning zero flux.")
347
+ return 0.0
348
+
349
+ # Skip for WINDOW, SKYLIGHT (handled via SHGC)
350
+ if component_type in [ComponentType.WINDOW, ComponentType.SKYLIGHT]:
351
+ logger.info(f"Skipping heat flux calculation for {component_type.value} component '{component.get('name', 'Unknown')}'.")
352
+ return 0.0
353
+
354
+ # Get CTF coefficients
355
+ ctf = cls.calculate_ctf_coefficients(component)
356
+ if not any(ctf.X + ctf.Y + ctf.Z + ctf.F):
357
+ logger.warning(f"Zero CTF coefficients for component '{component.get('name', 'Unknown')}'. Returning zero flux.")
358
+ return 0.0
359
+
360
+ # Extract hourly data
361
+ T_out = hourly_data.get('dry_bulb', 25.0)
362
+ dew_point = hourly_data.get('dew_point', T_out - 5.0)
363
+ wind_speed = hourly_data.get('wind_speed', 4.0)
364
+ total_sky_cover = hourly_data.get('total_sky_cover', 0.5)
365
+ T_in = 24.0 # Assume constant indoor temperature (adjust as needed)
366
+
367
+ # Get surface parameters and total incident radiation
368
+ surface_tilt, surface_azimuth, h_o, emissivity, absorptivity = solar_calc.get_surface_parameters(
369
+ component, building_info, wind_speed)
370
+
371
+ # Calculate total incident radiation (simplified, reuse solar_calc logic)
372
+ ghi = hourly_data.get('global_horizontal_radiation', 0.0)
373
+ dni = hourly_data.get('direct_normal_radiation', ghi * 0.7)
374
+ dhi = hourly_data.get('diffuse_horizontal_radiation', ghi * 0.3)
375
+ if ghi <= 0:
376
+ I_t = 0.0
377
+ else:
378
+ # Simplified radiation calculation (full calc in solar.py)
379
+ view_factor = (1 - math.cos(math.radians(surface_tilt))) / 2
380
+ ground_reflectivity = 0.2
381
+ cos_theta = max(math.cos(math.radians(surface_tilt)), 0.0) # Simplified for CTF
382
+ I_t = dni * cos_theta + dhi + ground_reflectivity * ghi * view_factor
383
+
384
+ # Calculate sol-air temperature
385
+ T_sol_air = solar_calc.calculate_sol_air_temperature(
386
+ T_out, I_t, absorptivity, emissivity, h_o, dew_point, total_sky_cover)
387
+
388
+ # Calculate heat flux using CTF (q_t = Σ X_i * T_sol_air(t-i) + Σ Z_i * T_in(t-i) - Σ F_i * q(t-i))
389
+ num_ctf = len(ctf.X)
390
+ q_t = 0.0
391
+ for i in range(num_ctf):
392
+ # Assume T_sol_air and T_in are constant for history (simplified, extend with history buffer if needed)
393
+ q_t += ctf.X[i] * T_sol_air + ctf.Z[i] * T_in
394
+ # Flux history (F) requires previous q values; assume zero for first calculation
395
+ q_t -= ctf.F[i] * 0.0 # Placeholder, implement history buffer for accurate F terms
396
+
397
+ logger.info(f"Calculated heat flux for component '{component.get('name', 'Unknown')}' at "
398
+ f"{hourly_data.get('month')}/{hourly_data.get('day')}/{hourly_data.get('hour')}: "
399
+ f"{q_t:.2f} W/m² (T_sol_air={T_sol_air:.2f}°C)")
400
+ return q_t