Energy Simulation
Overview
This skill implements building energy simulation and analysis. Calculate thermal loads, evaluate building envelope performance, and optimize systems for energy efficiency and code compliance.
Capabilities:
- Heating/cooling load calculations
- Envelope thermal analysis
- HVAC system sizing
- Energy code compliance
- Renewable energy integration
- Life cycle cost analysis
Quick Start
from dataclasses import dataclass, field
from typing import List, Dict, Optional, Tuple
from enum import Enum
import numpy as np
class WallType(Enum):
CONCRETE = "concrete"
BRICK = "brick"
WOOD_FRAME = "wood_frame"
STEEL_FRAME = "steel_frame"
CURTAIN_WALL = "curtain_wall"
@dataclass
class BuildingEnvelope:
wall_area_m2: float
wall_u_value: float # W/m²K
roof_area_m2: float
roof_u_value: float
floor_area_m2: float
floor_u_value: float
window_area_m2: float
window_u_value: float
window_shgc: float # Solar Heat Gain Coefficient
@dataclass
class ClimateData:
location: str
heating_degree_days: float # HDD base 18°C
cooling_degree_days: float # CDD base 18°C
design_temp_winter: float
design_temp_summer: float
def calculate_heat_loss(envelope: BuildingEnvelope, climate: ClimateData,
indoor_temp: float = 21) -> float:
"""Calculate design heat loss (W)"""
delta_t = indoor_temp - climate.design_temp_winter
# Transmission losses
wall_loss = envelope.wall_area_m2 * envelope.wall_u_value * delta_t
roof_loss = envelope.roof_area_m2 * envelope.roof_u_value * delta_t
floor_loss = envelope.floor_area_m2 * envelope.floor_u_value * delta_t * 0.5 # Ground factor
window_loss = envelope.window_area_m2 * envelope.window_u_value * delta_t
total_loss = wall_loss + roof_loss + floor_loss + window_loss
# Add infiltration estimate (simplified)
volume = envelope.floor_area_m2 * 3 # Assume 3m height
infiltration = volume * 0.5 * 0.33 * delta_t # 0.5 ACH, 0.33 Wh/m³K
return total_loss + infiltration
# Example
envelope = BuildingEnvelope(
wall_area_m2=500, wall_u_value=0.35,
roof_area_m2=200, roof_u_value=0.25,
floor_area_m2=200, floor_u_value=0.30,
window_area_m2=100, window_u_value=1.4, window_shgc=0.4
)
climate = ClimateData(
location="Moscow",
heating_degree_days=5000,
cooling_degree_days=300,
design_temp_winter=-25,
design_temp_summer=30
)
heat_loss = calculate_heat_loss(envelope, climate)
print(f"Design heat loss: {heat_loss/1000:.1f} kW")
Comprehensive Energy Analysis
Building Thermal Model
from dataclasses import dataclass, field
from typing import List, Dict, Optional, Tuple
from enum import Enum
import numpy as np
from datetime import datetime
@dataclass
class MaterialLayer:
name: str
thickness_m: float
conductivity: float # W/mK
density: float # kg/m³
specific_heat: float # J/kgK
@property
def resistance(self) -> float:
"""Thermal resistance R (m²K/W)"""
return self.thickness_m / self.conductivity if self.conductivity > 0 else 0
@dataclass
class WallAssembly:
name: str
layers: List[MaterialLayer]
inside_surface_resistance: float = 0.13 # m²K/W
outside_surface_resistance: float = 0.04
@property
def total_resistance(self) -> float:
return (self.inside_surface_resistance +
sum(layer.resistance for layer in self.layers) +
self.outside_surface_resistance)
@property
def u_value(self) -> float:
return 1 / self.total_resistance if self.total_resistance > 0 else 0
@dataclass
class Window:
name: str
u_value: float
shgc: float
visible_transmittance: float = 0.6
frame_fraction: float = 0.2
@dataclass
class Zone:
zone_id: str
name: str
floor_area_m2: float
volume_m3: float
occupancy: int
lighting_power_density: float # W/m²
equipment_power_density: float # W/m²
ventilation_rate: float # L/s per person
setpoint_heating: float = 21
setpoint_cooling: float = 24
@dataclass
class BuildingGeometry:
zones: List[Zone]
walls: List[Dict] # {zone, orientation, area, assembly}
windows: List[Dict] # {zone, orientation, area, window_type}
roofs: List[Dict] # {zone, area, assembly}
floors: List[Dict] # {zone, area, assembly, is_ground}
class ThermalCalculator:
"""Calculate building thermal loads"""
# Standard climate data (simplified)
CLIMATE_DB = {
'moscow': {
'hdd': 5000, 'cdd': 300,
'design_winter': -25, 'design_summer': 30,
'latitude': 55.75
},
'new_york': {
'hdd': 2500, 'cdd': 800,
'design_winter': -12, 'design_summer': 33,
'latitude': 40.71
},
'dubai': {
'hdd': 50, 'cdd': 3000,
'design_winter': 15, 'design_summer': 45,
'latitude': 25.20
}
}
def __init__(self, building: BuildingGeometry, location: str):
self.building = building
self.location = location.lower()
self.climate = self.CLIMATE_DB.get(self.location, self.CLIMATE_DB['moscow'])
def calculate_design_heating_load(self) -> Dict:
"""Calculate design heating load for each zone"""
delta_t = 21 - self.climate['design_winter']
results = {}
for zone in self.building.zones:
# Transmission losses
wall_loss = 0
window_loss = 0
roof_loss = 0
floor_loss = 0
for wall in self.building.walls:
if wall['zone'] == zone.zone_id:
u_value = wall['assembly'].u_value
wall_loss += wall['area'] * u_value * delta_t
for window in self.building.windows:
if window['zone'] == zone.zone_id:
window_loss += window['area'] * window['window_type'].u_value * delta_t
for roof in self.building.roofs:
if roof['zone'] == zone.zone_id:
u_value = roof['assembly'].u_value
roof_loss += roof['area'] * u_value * delta_t
for floor in self.building.floors:
if floor['zone'] == zone.zone_id:
u_value = floor['assembly'].u_value
factor = 0.5 if floor.get('is_ground', False) else 1.0
floor_loss += floor['area'] * u_value * delta_t * factor
# Infiltration
infiltration_loss = zone.volume_m3 * 0.5 * 0.33 * delta_t
# Ventilation (if mechanical)
ventilation_loss = zone.occupancy * zone.ventilation_rate * 1.2 * delta_t
total = wall_loss + window_loss + roof_loss + floor_loss + infiltration_loss + ventilation_loss
results[zone.zone_id] = {
'zone_name': zone.name,
'wall_loss_w': wall_loss,
'window_loss_w': window_loss,
'roof_loss_w': roof_loss,
'floor_loss_w': floor_loss,
'infiltration_w': infiltration_loss,
'ventilation_w': ventilation_loss,
'total_w': total,
'total_kw': total / 1000,
'w_per_m2': total / zone.floor_area_m2
}
return results
def calculate_design_cooling_load(self) -> Dict:
"""Calculate design cooling load for each zone"""
delta_t = self.climate['design_summer'] - 24
results = {}
for zone in self.building.zones:
# Transmission gains
transmission_gain = 0
for wall in self.building.walls:
if wall['zone'] == zone.zone_id:
u_value = wall['assembly'].u_value
# Apply sol-air temperature correction for orientation
sol_air_delta = delta_t + self._get_so