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)}") |