Spaces:
Sleeping
Sleeping
""" | |
Reference data structures for HVAC Load Calculator. | |
This module contains reference data for materials, construction types, and other HVAC-related data. | |
""" | |
from typing import Dict, List, Any, Optional | |
import pandas as pd | |
import json | |
import os | |
import logging | |
from uuid import uuid4 | |
# Configure logging | |
logging.basicConfig(level=logging.INFO) | |
logger = logging.getLogger(__name__) | |
# Define paths | |
DATA_DIR = os.path.dirname(os.path.abspath(__file__)) | |
DEFAULT_DATA_FILE = os.path.join(DATA_DIR, "reference_data.json") | |
class ReferenceData: | |
"""Class for managing reference data for the HVAC calculator.""" | |
def __init__(self): | |
"""Initialize reference data structures.""" | |
self.materials = {} | |
self.wall_types = {} | |
self.roof_types = {} | |
self.floor_types = {} | |
self.window_types = {} | |
self.door_types = {} | |
self.internal_loads = {} | |
try: | |
self._load_all_data() | |
except Exception as e: | |
logger.error(f"Error initializing reference data: {str(e)}") | |
raise | |
def _load_all_data(self) -> None: | |
"""Load all reference data, attempting to load from JSON first.""" | |
try: | |
if os.path.exists(DEFAULT_DATA_FILE): | |
self._load_from_json(DEFAULT_DATA_FILE) | |
else: | |
self._load_default_data() | |
self.export_to_json(DEFAULT_DATA_FILE) | |
except Exception as e: | |
logger.error(f"Error loading reference data: {str(e)}") | |
self._load_default_data() # Fallback to default data | |
def _load_default_data(self) -> None: | |
"""Load default reference data.""" | |
self.materials = self._load_materials() | |
self.wall_types = self._load_wall_types() | |
self.roof_types = self._load_roof_types() | |
self.floor_types = self._load_floor_types() | |
self.window_types = self._load_window_types() | |
self.door_types = self._load_door_types() | |
self.internal_loads = self._load_internal_loads() | |
def _load_materials(self) -> Dict[str, Dict[str, Any]]: | |
""" | |
Load material properties. | |
Returns: | |
Dictionary of material properties | |
""" | |
return { | |
"brick": { | |
"id": str(uuid4()), | |
"name": "Common Brick", | |
"conductivity": 0.72, # W/(m·K) | |
"density": 1920, # kg/m³ | |
"specific_heat": 840, # J/(kg·K) | |
"typical_thickness": 0.1, # m | |
"emissivity": 0.9, | |
"solar_absorptance": 0.7 | |
}, | |
"concrete": { | |
"id": str(uuid4()), | |
"name": "Concrete", | |
"conductivity": 1.4, # W/(m·K) | |
"density": 2300, # kg/m³ | |
"specific_heat": 880, # J/(kg·K) | |
"typical_thickness": 0.2, # m | |
"emissivity": 0.92, | |
"solar_absorptance": 0.65 | |
}, | |
"mineral_wool": { | |
"id": str(uuid4()), | |
"name": "Mineral Wool Insulation", | |
"conductivity": 0.04, # W/(m·K) | |
"density": 30, # kg/m³ | |
"specific_heat": 840, # J/(kg·K) | |
"typical_thickness": 0.1, # m | |
"emissivity": 0.9, | |
"solar_absorptance": 0.6 | |
}, | |
# Additional materials | |
"polyurethane_foam": { | |
"id": str(uuid4()), | |
"name": "Polyurethane Foam", | |
"conductivity": 0.025, # W/(m·K) | |
"density": 40, # kg/m³ | |
"specific_heat": 1500, # J/(kg·K) | |
"typical_thickness": 0.05, # m | |
"emissivity": 0.9, | |
"solar_absorptance": 0.6 | |
}, | |
"fiberglass_insulation": { | |
"id": str(uuid4()), | |
"name": "Fiberglass Insulation", | |
"conductivity": 0.045, # W/(m·K) | |
"density": 12, # kg/m³ | |
"specific_heat": 850, # J/(kg·K) | |
"typical_thickness": 0.15, # m | |
"emissivity": 0.9, | |
"solar_absorptance": 0.6 | |
}, | |
"stucco": { | |
"id": str(uuid4()), | |
"name": "Stucco", | |
"conductivity": 0.7, # W/(m·K) | |
"density": 1850, # kg/m³ | |
"specific_heat": 900, # J/(kg·K) | |
"typical_thickness": 0.025, # m | |
"emissivity": 0.92, | |
"solar_absorptance": 0.5 | |
} | |
# Add more materials as needed | |
} | |
def _load_wall_types(self) -> Dict[str, Dict[str, Any]]: | |
""" | |
Load predefined wall types. | |
Returns: | |
Dictionary of wall types with properties | |
""" | |
return { | |
"brick_veneer_wood_frame": { | |
"id": str(uuid4()), | |
"name": "Brick Veneer with Wood Frame", | |
"description": "Brick veneer with wood frame, insulation, and gypsum board", | |
"u_value": 0.35, # W/(m²·K) | |
"wall_group": "B", | |
"layers": [ | |
{"material": "brick", "thickness": 0.1}, | |
{"material": "air_gap", "thickness": 0.025}, | |
{"material": "wood", "thickness": 0.038}, | |
{"material": "mineral_wool", "thickness": 0.089}, | |
{"material": "gypsum_board", "thickness": 0.0125} | |
], | |
"thermal_mass": 180, # kg/m² | |
"color": "Medium" | |
}, | |
"insulated_concrete_form": { | |
"id": str(uuid4()), | |
"name": "Insulated Concrete Form", | |
"description": "ICF with EPS insulation and concrete core", | |
"u_value": 0.25, # W/(m²·K) | |
"wall_group": "C", | |
"layers": [ | |
{"material": "eps_insulation", "thickness": 0.05}, | |
{"material": "concrete", "thickness": 0.15}, | |
{"material": "eps_insulation", "thickness": 0.05}, | |
{"material": "gypsum_board", "thickness": 0.0125} | |
], | |
"thermal_mass": 220, # kg/m² | |
"color": "Light" | |
}, | |
# Additional wall types | |
"sip_panel": { | |
"id": str(uuid4()), | |
"name": "Structural Insulated Panel", | |
"description": "SIP with OSB and EPS core", | |
"u_value": 0.28, # W/(m²·K) | |
"wall_group": "A", | |
"layers": [ | |
{"material": "wood", "thickness": 0.012}, | |
{"material": "eps_insulation", "thickness": 0.15}, | |
{"material": "wood", "thickness": 0.012}, | |
{"material": "gypsum_board", "thickness": 0.0125} | |
], | |
"thermal_mass": 80, # kg/m² | |
"color": "Light" | |
} | |
} | |
def _load_roof_types(self) -> Dict[str, Dict[str, Any]]: | |
""" | |
Load predefined roof types. | |
Returns: | |
Dictionary of roof types with properties | |
""" | |
return { | |
"flat_roof_concrete": { | |
"id": str(uuid4()), | |
"name": "Flat Concrete Roof with Insulation", | |
"description": "Flat concrete roof with insulation and ceiling", | |
"u_value": 0.25, # W/(m²·K) | |
"roof_group": "B", | |
"layers": [ | |
{"material": "concrete", "thickness": 0.15}, | |
{"material": "eps_insulation", "thickness": 0.15}, | |
{"material": "gypsum_board", "thickness": 0.0125} | |
], | |
"solar_absorptance": 0.7, | |
"emissivity": 0.9 | |
}, | |
"green_roof": { | |
"id": str(uuid4()), | |
"name": "Green Roof", | |
"description": "Vegetated roof with insulation and drainage", | |
"u_value": 0.22, # W/(m²·K) | |
"roof_group": "A", | |
"layers": [ | |
{"material": "soil", "thickness": 0.1}, | |
{"material": "eps_insulation", "thickness": 0.1}, | |
{"material": "concrete", "thickness": 0.1}, | |
{"material": "gypsum_board", "thickness": 0.0125} | |
], | |
"solar_absorptance": 0.5, | |
"emissivity": 0.95 | |
} | |
} | |
def _load_floor_types(self) -> Dict[str, Dict[str, Any]]: | |
""" | |
Load predefined floor types. | |
Returns: | |
Dictionary of floor types with properties | |
""" | |
return { | |
"concrete_slab_on_grade": { | |
"id": str(uuid4()), | |
"name": "Concrete Slab on Grade", | |
"description": "Concrete slab on grade with insulation", | |
"u_value": 0.3, # W/(m²·K) | |
"is_ground_contact": True, | |
"layers": [ | |
{"material": "concrete", "thickness": 0.1}, | |
{"material": "eps_insulation", "thickness": 0.05} | |
], | |
"thermal_mass": 230 # kg/m² | |
}, | |
"radiant_floor": { | |
"id": str(uuid4()), | |
"name": "Radiant Floor", | |
"description": "Concrete floor with radiant heating and insulation", | |
"u_value": 0.27, # W/(m²·K) | |
"is_ground_contact": True, | |
"layers": [ | |
{"material": "tile", "thickness": 0.015}, | |
{"material": "concrete", "thickness": 0.1}, | |
{"material": "eps_insulation", "thickness": 0.075} | |
], | |
"thermal_mass": 240 # kg/m² | |
} | |
} | |
def _load_window_types(self) -> Dict[str, Dict[str, Any]]: | |
""" | |
Load predefined window types. | |
Returns: | |
Dictionary of window types with properties | |
""" | |
return { | |
"double_glazed_argon_low_e": { | |
"id": str(uuid4()), | |
"name": "Double Glazed with Argon and Low-E", | |
"description": "Double glazed window with argon fill, low-e coating, and vinyl frame", | |
"u_value": 1.4, # W/(m²·K) | |
"shgc": 0.4, | |
"vt": 0.7, | |
"glazing_layers": 2, | |
"gas_fill": "Argon", | |
"frame_type": "Vinyl", | |
"low_e_coating": True, | |
"frame_factor": 0.15 | |
}, | |
"electrochromic_window": { | |
"id": str(uuid4()), | |
"name": "Electrochromic Window", | |
"description": "Smart window with dynamic tinting", | |
"u_value": 1.2, # W/(m²·K) | |
"shgc": 0.35, | |
"vt": 0.65, | |
"glazing_layers": 2, | |
"gas_fill": "Argon", | |
"frame_type": "Fiberglass", | |
"low_e_coating": True, | |
"frame_factor": 0.12 | |
} | |
} | |
def _load_door_types(self) -> Dict[str, Dict[str, Any]]: | |
""" | |
Load predefined door types. | |
Returns: | |
Dictionary of door types with properties | |
""" | |
return { | |
"insulated_steel_door": { | |
"id": str(uuid4()), | |
"name": "Insulated Steel Door", | |
"description": "Insulated steel door with no glazing", | |
"u_value": 1.2, # W/(m²·K) | |
"glazing_percentage": 0, | |
"door_type": "Solid", | |
"thermal_mass": 50 # kg/m² | |
}, | |
"insulated_fiberglass_door": { | |
"id": str(uuid4()), | |
"name": "Insulated Fiberglass Door", | |
"description": "Insulated fiberglass door with small glazing", | |
"u_value": 1.5, # W/(m²·K) | |
"glazing_percentage": 10, | |
"door_type": "Partially glazed", | |
"shgc": 0.7, | |
"vt": 0.8, | |
"thermal_mass": 40 # kg/m² | |
} | |
} | |
def _load_internal_loads(self) -> Dict[str, Dict[str, Any]]: | |
""" | |
Load internal load data. | |
Returns: | |
Dictionary of internal load types with properties | |
""" | |
return { | |
"occupancy": { | |
"office_typing": { | |
"id": str(uuid4()), | |
"name": "Office Typing", | |
"sensible_heat": 75, # W per person | |
"latent_heat": 55, # W per person | |
"metabolic_rate": 1.2 # met | |
}, | |
"retail_sales": { | |
"id": str(uuid4()), | |
"name": "Retail Sales", | |
"sensible_heat": 80, # W per person | |
"latent_heat": 70, # W per person | |
"metabolic_rate": 1.4 # met | |
} | |
}, | |
"lighting": { | |
"led_high_efficiency": { | |
"id": str(uuid4()), | |
"name": "High Efficiency LED", | |
"power_density_range": [4, 8], # W/m² | |
"heat_to_space": 0.85, | |
"efficacy": 120 # lm/W | |
} | |
}, | |
"equipment": { | |
"computer_workstation": { | |
"id": str(uuid4()), | |
"name": "Computer Workstation", | |
"power_density_range": [15, 25], # W/m² | |
"sensible_fraction": 0.95, | |
"latent_fraction": 0.05 | |
} | |
} | |
} | |
def _load_from_json(self, file_path: str) -> None: | |
""" | |
Load reference data from JSON file. | |
Args: | |
file_path: Path to JSON file | |
""" | |
try: | |
with open(file_path, 'r') as f: | |
data = json.load(f) | |
self.materials = data.get("materials", self.materials) | |
self.wall_types = data.get("wall_types", self.wall_types) | |
self.roof_types = data.get("roof_types", self.roof_types) | |
self.floor_types = data.get("floor_types", self.floor_types) | |
self.window_types = data.get("window_types", self.window_types) | |
self.door_types = data.get("door_types", self.door_types) | |
self.internal_loads = data.get("internal_loads", self.internal_loads) | |
logger.info(f"Successfully loaded reference data from {file_path}") | |
except Exception as e: | |
logger.error(f"Error loading JSON data from {file_path}: {str(e)}") | |
raise | |
def export_to_json(self, file_path: str) -> None: | |
""" | |
Export all reference data to a JSON file. | |
Args: | |
file_path: Path to the output JSON file | |
""" | |
try: | |
data = { | |
"materials": self.materials, | |
"wall_types": self.wall_types, | |
"roof_types": self.roof_types, | |
"floor_types": self.floor_types, | |
"window_types": self.window_types, | |
"door_types": self.door_types, | |
"internal_loads": self.internal_loads | |
} | |
with open(file_path, 'w') as f: | |
json.dump(data, f, indent=4) | |
logger.info(f"Successfully exported reference data to {file_path}") | |
except Exception as e: | |
logger.error(f"Error exporting to JSON: {str(e)}") | |
raise | |
# Getter methods with validation | |
def get_material(self, material_id: str) -> Optional[Dict[str, Any]]: | |
return self.materials.get(material_id) | |
def get_wall_type(self, wall_type_id: str) -> Optional[Dict[str, Any]]: | |
return self.wall_types.get(wall_type_id) | |
def get_roof_type(self, roof_type_id: str) -> Optional[Dict[str, Any]]: | |
return self.roof_types.get(roof_type_id) | |
def get_floor_type(self, floor_type_id: str) -> Optional[Dict[str, Any]]: | |
return self.floor_types.get(floor_type_id) | |
def get_window_type(self, window_type_id: str) -> Optional[Dict[str, Any]]: | |
return self.window_types.get(window_type_id) | |
def get_door_type(self, door_type_id: str) -> Optional[Dict[str, Any]]: | |
return self.door_types.get(door_type_id) | |
def get_internal_load(self, load_type: str, load_id: str) -> Optional[Dict[str, Any]]: | |
return self.internal_loads.get(load_type, {}).get(load_id) | |
# Singleton instance | |
try: | |
reference_data = ReferenceData() | |
except Exception as e: | |
logger.error(f"Failed to create ReferenceData instance: {str(e)}") | |
raise | |
if __name__ == "__main__": | |
try: | |
reference_data.export_to_json(DEFAULT_DATA_FILE) | |
except Exception as e: | |
logger.error(f"Error exporting default data: {str(e)}") |