Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Building energy simulation and analysis for construction. Calculate heating/cooling loads, evaluate envelope performance, optimize HVAC sizing, and ensure energy code compliance.
.claude/skills/datadrivenconstruction-energy-simulation/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 297% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 390% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 70% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 322% | 0% |
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:
pythonfrom 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")
pythonfrom 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_sol_air_correction(wall['orientation']) transmission_gain += wall['area'] * u_value * sol_air_delta # Window solar gains solar_gain = 0 for window in self.building.windows: if window['zone'] == zone.zone_id: shgc = window['window_type'].shgc irradiance = self._get_solar_irradiance(window['orientation']) solar_gain += window['area'] * shgc * irradiance # Window conduction window_conduction = 0 for window in self.building.windows: if window['zone'] == zone.zone_id: window_conduction += window['area'] * window['window_type'].u_value * delta_t # Internal gains lighting_gain = zone.floor_area_m2 * zone.lighting_power_density equipment_gain = zone.floor_area_m2 * zone.equipment_power_density people_gain = zone.occupancy * 75 # W per person sensible # Ventilation ventilation_gain = zone.occupancy * zone.ventilation_rate * 1.2 * delta_t total = (transmission_gain + solar_gain + window_conduction + lighting_gain + equipment_gain + people_gain + ventilation_gain) results[zone.zone_id] = { 'zone_name': zone.name, 'transmission_gain_w': transmission_gain, 'solar_gain_w': solar_gain, 'window_conduction_w': window_conduction, 'lighting_gain_w': lighting_gain, 'equipment_gain_w': equipment_gain, 'people_gain_w': people_gain, 'ventilation_gain_w': ventilation_gain, 'total_w': total, 'total_kw': total / 1000, 'w_per_m2': total / zone.floor_area_m2 } return results def _get_sol_air_correction(self, orientation: str) -> float: """Get sol-air temperature correction by orientation""" corrections = { 'north': 0, 'south': 8, 'east': 4, 'west': 6, 'northeast': 2, 'northwest': 3, 'southeast': 6, 'southwest': 7 } return corrections.get(orientation.lower(), 3) def _get_solar_irradiance(self, orientation: str) -> float: """Get design solar irradiance W/m² by orientation""" # Simplified peak values irradiance = { 'north': 150, 'south': 450, 'east': 350, 'west': 350, 'northeast': 200, 'northwest': 200, 'southeast': 400, 'southwest': 400 } return irradiance.get(orientation.lower(), 300)
pythonclass HVACSizer: """Size HVAC systems based on loads""" def __init__(self, calculator: ThermalCalculator): self.calculator = calculator def size_heating_system(self, safety_factor: float = 1.15) -> Dict: """Size heating system""" heating_loads = self.calculator.calculate_design_heating_load() total_load = sum(z['total_kw'] for z in heating_loads.values()) sized_capacity = total_load * safety_factor # Recommend system type if sized_capacity < 15: system_type = "Split system heat pump" elif sized_capacity < 50: system_type = "Packaged rooftop unit" elif sized_capacity < 200: system_type = "Central boiler with radiators" else: system_type = "Central plant with multiple boilers" return { 'total_load_kw': total_load, 'sized_capacity_kw': sized_capacity, 'safety_factor': safety_factor, 'recommended_system': system_type, 'zone_loads': heating_loads } def size_cooling_system(self, safety_factor: float = 1.1) -> Dict: """Size cooling system""" cooling_loads = self.calculator.calculate_design_cooling_load() total_load = sum(z['total_kw'] for z in cooling_loads.values()) sized_capacity = total_load * safety_factor # Convert to tons capacity_tons = sized_capacity / 3.517 # Recommend system type if capacity_tons < 5: system_type = "Split system DX" elif capacity_tons < 20: system_type = "VRF system" elif capacity_tons < 100: system_type = "Chilled water with AHUs" else: system_type = "Central chiller plant" return { 'total_load_kw': total_load, 'total_load_tons': capacity_tons, 'sized_capacity_kw': sized_capacity, 'sized_capacity_tons': capacity_tons * safety_factor, 'safety_factor': safety_factor, 'recommended_system': system_type, 'zone_loads': cooling_loads } def estimate_annual_energy(self) -> Dict: """Estimate annual energy consumption""" climate = self.calculator.climate heating_loads = self.calculator.calculate_design_heating_load() cooling_loads = self.calculator.calculate_design_cooling_load() total_heating_load = sum(z['total_kw'] for z in heating_loads.values()) total_cooling_load = sum(z['total_kw'] for z in cooling_loads.values()) # Simplified degree-day calculation # Heating energy = load * HDD * 24 / delta_t_design delta_t_heating = 21 - climate['design_winter'] heating_kwh = total_heating_load * climate['hdd'] * 24 / delta_t_heating / 1000 delta_t_cooling = climate['design_summer'] - 24 cooling_kwh = total_cooling_load * climate['cdd'] * 24 / delta_t_cooling / 1000 if delta_t_cooling > 0 else 0 # Apply efficiency factors heating_fuel_efficiency = 0.9 # Gas boiler cooling_cop = 3.5 # Chiller COP heating_consumption = heating_kwh / heating_fuel_efficiency cooling_consumption = cooling_kwh / cooling_cop return { 'heating_load_kw': total_heating_load, 'cooling_load_kw': total_cooling_load, 'annual_heating_kwh': heating_kwh, 'annual_cooling_kwh': cooling_kwh, 'heating_fuel_kwh': heating_consumption, 'cooling_electricity_kwh': cooling_consumption, 'total_hvac_energy_kwh': heating_consumption + cooling_consumption }
python@dataclass class EnergyCodeRequirements: code_name: str climate_zone: str wall_u_max: float roof_u_max: float floor_u_max: float window_u_max: float window_shgc_max: float lighting_lpd_max: float # W/m² class ComplianceChecker: """Check energy code compliance""" CODES = { 'ASHRAE_90.1_2019_4A': EnergyCodeRequirements( code_name="ASHRAE 90.1-2019", climate_zone="4A", wall_u_max=0.45, roof_u_max=0.27, floor_u_max=0.32, window_u_max=2.0, window_shgc_max=0.40, lighting_lpd_max=9.0 ), 'IECC_2021_5A': EnergyCodeRequirements( code_name="IECC 2021", climate_zone="5A", wall_u_max=0.35, roof_u_max=0.20, floor_u_max=0.30, window_u_max=1.7, window_shgc_max=0.40, lighting_lpd_max=8.5 ) } def __init__(self, code_key: str): self.requirements = self.CODES.get(code_key) if not self.requirements: raise ValueError(f"Unknown code: {code_key}") def check_envelope(self, building: BuildingGeometry) -> Dict: """Check envelope compliance""" results = { 'code': self.requirements.code_name, 'climate_zone': self.requirements.climate_zone, 'compliant': True, 'issues': [] } # Check walls for wall in building.walls: u_value = wall['assembly'].u_value if u_value > self.requirements.wall_u_max: results['compliant'] = False results['issues'].append({ 'element': f"Wall {wall['zone']} {wall['orientation']}", 'actual': u_value, 'required': self.requirements.wall_u_max, 'issue': 'Exceeds maximum U-value' }) # Check windows for window in building.windows: u_value = window['window_type'].u_value shgc = window['window_type'].shgc if u_value > self.requirements.window_u_max: results['compliant'] = False results['issues'].append({ 'element': f"Window {window['zone']} {window['orientation']}", 'actual': u_value, 'required': self.requirements.window_u_max, 'issue': 'Exceeds maximum U-value' }) if shgc > self.requirements.window_shgc_max: results['compliant'] = False results['issues'].append({ 'element': f"Window {window['zone']} {window['orientation']}", 'actual': shgc, 'required': self.requirements.window_shgc_max, 'issue': 'Exceeds maximum SHGC' }) # Check roof for roof in building.roofs: u_value = roof['assembly'].u_value if u_value > self.requirements.roof_u_max: results['compliant'] = False results['issues'].append({ 'element': f"Roof {roof['zone']}", 'actual': u_value, 'required': self.requirements.roof_u_max, 'issue': 'Exceeds maximum U-value' }) return results def check_lighting(self, zones: List[Zone]) -> Dict: """Check lighting power density compliance""" results = { 'compliant': True, 'issues': [] } for zone in zones: if zone.lighting_power_density > self.requirements.lighting_lpd_max: results['compliant'] = False results['issues'].append({ 'zone': zone.name, 'actual_lpd': zone.lighting_power_density, 'required_max': self.requirements.lighting_lpd_max }) return results
| Component | Good U-Value | Code Maximum | |-----------|--------------|--------------| | Wall | < 0.25 W/m²K | 0.35-0.45 | | Roof | < 0.15 W/m²K | 0.20-0.27 | | Floor | < 0.20 W/m²K | 0.25-0.32 | | Window | < 1.2 W/m²K | 1.7-2.0 |
co2-estimation for carbon analysiscost-prediction for energy cost modelingbim-validation-pipeline for model integration| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | fail→pass | 15,011 | 26,314 | +75% | 1 | 1 | 0% | 2,758 | 10,939 | +297% | 0 | 0 | — |
case-01 | fail→fail | 20,166 | 28,183 | +40% | 1 | 1 | 0% | 4,087 | 11,702 | +186% | 0 | 0 | — |
case-03 | fail→pass | 23,566 | 18,395 | -22% | 1 | 1 | 0% | 4,920 | 9,084 | +85% | 0 | 0 | — |
case-04 | fail→pass | 15,044 | 11,963 | -20% | 1 | 1 | 0% | 1,647 | 8,070 | +390% | 0 | 0 | — |
case-05 | fail→pass | 21,465 | 9,375 | -56% | 1 | 1 | 0% | 4,399 | 7,488 | +70% | 0 | 0 | — |
case-06 | pass→pass | 12,130 | 7,751 | -36% | 1 | 1 | 0% | 2,696 | 7,311 | +171% | 0 | 0 | — |
case-16 | pass→pass | 10,494 | 4,881 | -53% | 1 | 1 | 0% | 1,858 | 6,275 | +238% | 0 | 0 | — |
case-07 | fail→pass | 38,202 | 10,277 | -73% | 1 | 1 | 0% | 1,715 | 7,234 | +322% | 0 | 0 | — |
case-08 | fail→fail | 17,971 | 15,038 | -16% | 1 | 1 | 0% | 3,150 | 8,413 | +167% | 0 | 0 | — |
case-09 | fail→fail | 15,852 | 11,114 | -30% | 1 | 1 | 0% | 2,497 | 7,591 | +204% | 0 | 0 | — |
case-10 | fail→pass | 19,466 | 10,756 | -45% | 1 | 1 | 0% | 3,016 | 7,242 | +140% | 0 | 0 | — |
case-17 | pass→pass | 17,621 | 9,980 | -43% | 1 | 1 | 0% | 3,189 | 7,195 | +126% | 0 | 0 | — |
case-11 | pass→pass | 8,614 | 7,549 | -12% | 1 | 1 | 0% | 1,756 | 7,009 | +299% | 0 | 0 | — |
case-12 | fail→pass | 10,805 | 2,932 | -73% | 1 | 1 | 0% | 2,025 | 6,075 | +200% | 0 | 0 | — |
case-13 | fail→pass | 13,228 | 1,958 | -85% | 1 | 1 | 0% | 2,526 | 5,795 | +129% | 0 | 0 | — |
case-14 | fail→pass | 9,851 | 8,728 | -11% | 1 | 1 | 0% | 2,050 | 7,195 | +251% | 0 | 0 | — |
case-15 | fail→pass | 15,870 | 7,686 | -52% | 1 | 1 | 0% | 2,700 | 6,997 | +159% | 0 | 0 | — |
case-18 | fail→fail | 17,746 | 20,162 | +14% | 1 | 1 | 0% | 2,970 | 9,092 | +206% | 0 | 0 | — |
case-19 | pass→pass | 15,843 | 3,224 | -80% | 1 | 1 | 0% | 2,771 | 6,084 | +120% | 0 | 0 | — |
case-20 | fail→fail | 21,930 | 19,794 | -10% | 1 | 1 | 0% | 4,529 | 9,578 | +111% | 0 | 0 | — |
case-21 | fail→fail | 10,750 | 15,123 | +41% | 1 | 1 | 0% | 2,134 | 8,400 | +294% | 0 | 0 | — |
case-22 | fail→fail | 14,699 | 13,611 | -7% | 1 | 1 | 0% | 2,586 | 8,286 | +220% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +45 percentage points is the difference between those two pass rates over the 21 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.