""" 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 # Define paths DATA_DIR = os.path.dirname(os.path.abspath(__file__)) class ReferenceData: """Class for managing reference data for the HVAC calculator.""" def __init__(self): """Initialize reference data structures.""" 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 from reference data. Returns: Dictionary of material properties """ # This would typically load from a JSON or CSV file # For now, we'll define some common materials inline return { "brick": { "name": "Common Brick", "conductivity": 0.72, # W/(m·K) "density": 1920, # kg/m³ "specific_heat": 840, # J/(kg·K) "typical_thickness": 0.1 # m }, "concrete": { "name": "Concrete", "conductivity": 1.4, # W/(m·K) "density": 2300, # kg/m³ "specific_heat": 880, # J/(kg·K) "typical_thickness": 0.2 # m }, "mineral_wool": { "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 }, "eps_insulation": { "name": "EPS Insulation", "conductivity": 0.035, # W/(m·K) "density": 25, # kg/m³ "specific_heat": 1400, # J/(kg·K) "typical_thickness": 0.1 # m }, "gypsum_board": { "name": "Gypsum Board", "conductivity": 0.25, # W/(m·K) "density": 900, # kg/m³ "specific_heat": 1000, # J/(kg·K) "typical_thickness": 0.0125 # m }, "wood": { "name": "Wood (Pine)", "conductivity": 0.14, # W/(m·K) "density": 500, # kg/m³ "specific_heat": 1600, # J/(kg·K) "typical_thickness": 0.025 # m }, "steel": { "name": "Steel", "conductivity": 50, # W/(m·K) "density": 7800, # kg/m³ "specific_heat": 450, # J/(kg·K) "typical_thickness": 0.005 # m }, "glass": { "name": "Glass", "conductivity": 1.0, # W/(m·K) "density": 2500, # kg/m³ "specific_heat": 840, # J/(kg·K) "typical_thickness": 0.006 # m }, "air_gap": { "name": "Air Gap", "conductivity": 0.024, # W/(m·K) "density": 1.2, # kg/m³ "specific_heat": 1000, # J/(kg·K) "typical_thickness": 0.025 # m }, "concrete_block": { "name": "Concrete Block", "conductivity": 0.51, # W/(m·K) "density": 1400, # kg/m³ "specific_heat": 1000, # J/(kg·K) "typical_thickness": 0.2 # m }, "asphalt_shingle": { "name": "Asphalt Shingle", "conductivity": 0.7, # W/(m·K) "density": 1100, # kg/m³ "specific_heat": 1260, # J/(kg·K) "typical_thickness": 0.006 # m }, "carpet": { "name": "Carpet", "conductivity": 0.06, # W/(m·K) "density": 200, # kg/m³ "specific_heat": 1300, # J/(kg·K) "typical_thickness": 0.01 # m }, "vinyl_flooring": { "name": "Vinyl Flooring", "conductivity": 0.17, # W/(m·K) "density": 1200, # kg/m³ "specific_heat": 1460, # J/(kg·K) "typical_thickness": 0.003 # m } } def _load_wall_types(self) -> Dict[str, Dict[str, Any]]: """ Load predefined wall types from reference data. Returns: Dictionary of wall types with properties """ return { "brick_veneer_wood_frame": { "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", # ASHRAE wall group "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} ] }, "concrete_block_insulated": { "name": "Concrete block with interior insulation", "description": "Concrete block wall with interior insulation and gypsum board", "u_value": 0.48, # W/(m²·K) "wall_group": "C", # ASHRAE wall group "layers": [ {"material": "concrete_block", "thickness": 0.2}, {"material": "eps_insulation", "thickness": 0.05}, {"material": "gypsum_board", "thickness": 0.0125} ] }, "precast_concrete_panel": { "name": "Precast concrete panel", "description": "Precast concrete panel with insulation and gypsum board", "u_value": 0.45, # W/(m²·K) "wall_group": "D", # ASHRAE wall group "layers": [ {"material": "concrete", "thickness": 0.1}, {"material": "eps_insulation", "thickness": 0.075}, {"material": "gypsum_board", "thickness": 0.0125} ] }, "metal_panel_insulated": { "name": "Metal panel with insulation", "description": "Metal panel wall with insulation and interior finish", "u_value": 0.4, # W/(m²·K) "wall_group": "E", # ASHRAE wall group "layers": [ {"material": "steel", "thickness": 0.001}, {"material": "mineral_wool", "thickness": 0.1}, {"material": "gypsum_board", "thickness": 0.0125} ] }, "wood_frame_wall": { "name": "Wood frame wall", "description": "Wood frame wall with insulation and gypsum board", "u_value": 0.3, # W/(m²·K) "wall_group": "A", # ASHRAE wall group "layers": [ {"material": "wood", "thickness": 0.019}, {"material": "air_gap", "thickness": 0.025}, {"material": "wood", "thickness": 0.038}, {"material": "mineral_wool", "thickness": 0.14}, {"material": "gypsum_board", "thickness": 0.0125} ] } } def _load_roof_types(self) -> Dict[str, Dict[str, Any]]: """ Load predefined roof types from reference data. Returns: Dictionary of roof types with properties """ return { "flat_roof_concrete": { "name": "Flat concrete roof with insulation", "description": "Flat concrete roof with insulation and ceiling", "u_value": 0.25, # W/(m²·K) "roof_group": "B", # ASHRAE roof group "layers": [ {"material": "concrete", "thickness": 0.15}, {"material": "eps_insulation", "thickness": 0.15}, {"material": "gypsum_board", "thickness": 0.0125} ] }, "pitched_roof_wood": { "name": "Pitched wood roof with insulation", "description": "Pitched wood roof with insulation and ceiling", "u_value": 0.2, # W/(m²·K) "roof_group": "A", # ASHRAE roof group "layers": [ {"material": "asphalt_shingle", "thickness": 0.006}, {"material": "wood", "thickness": 0.019}, {"material": "air_gap", "thickness": 0.025}, {"material": "mineral_wool", "thickness": 0.2}, {"material": "gypsum_board", "thickness": 0.0125} ] }, "metal_deck_roof": { "name": "Metal deck roof with insulation", "description": "Metal deck roof with insulation and ceiling", "u_value": 0.3, # W/(m²·K) "roof_group": "C", # ASHRAE roof group "layers": [ {"material": "steel", "thickness": 0.001}, {"material": "eps_insulation", "thickness": 0.1}, {"material": "air_gap", "thickness": 0.1}, {"material": "gypsum_board", "thickness": 0.0125} ] } } def _load_floor_types(self) -> Dict[str, Dict[str, Any]]: """ Load predefined floor types from reference data. Returns: Dictionary of floor types with properties """ return { "concrete_slab_on_grade": { "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} ] }, "suspended_concrete_floor": { "name": "Suspended concrete floor", "description": "Suspended concrete floor with insulation", "u_value": 0.25, # W/(m²·K) "is_ground_contact": False, "layers": [ {"material": "concrete", "thickness": 0.15}, {"material": "eps_insulation", "thickness": 0.1}, {"material": "gypsum_board", "thickness": 0.0125} ] }, "wood_joist_floor": { "name": "Wood joist floor", "description": "Wood joist floor with insulation", "u_value": 0.22, # W/(m²·K) "is_ground_contact": False, "layers": [ {"material": "wood", "thickness": 0.025}, {"material": "air_gap", "thickness": 0.15}, {"material": "mineral_wool", "thickness": 0.15}, {"material": "gypsum_board", "thickness": 0.0125} ] }, "carpet_on_concrete": { "name": "Carpet on concrete", "description": "Carpet on concrete slab with insulation", "u_value": 0.28, # W/(m²·K) "is_ground_contact": True, "layers": [ {"material": "carpet", "thickness": 0.01}, {"material": "concrete", "thickness": 0.1}, {"material": "eps_insulation", "thickness": 0.05} ] } } def _load_window_types(self) -> Dict[str, Dict[str, Any]]: """ Load predefined window types from reference data. Returns: Dictionary of window types with properties """ return { "single_glazed": { "name": "Single glazed window", "description": "Single glazed window with aluminum frame", "u_value": 5.8, # W/(m²·K) "shgc": 0.86, # Solar Heat Gain Coefficient "vt": 0.9, # Visible Transmittance "glazing_layers": 1, "gas_fill": "Air", "frame_type": "Aluminum", "low_e_coating": False }, "double_glazed_air": { "name": "Double glazed window with air", "description": "Double glazed window with air gap and aluminum frame", "u_value": 2.8, # W/(m²·K) "shgc": 0.76, # Solar Heat Gain Coefficient "vt": 0.81, # Visible Transmittance "glazing_layers": 2, "gas_fill": "Air", "frame_type": "Aluminum", "low_e_coating": False }, "double_glazed_argon_low_e": { "name": "Double glazed window with argon and low-e coating", "description": "Double glazed window with argon fill, low-e coating, and vinyl frame", "u_value": 1.4, # W/(m²·K) "shgc": 0.4, # Solar Heat Gain Coefficient "vt": 0.7, # Visible Transmittance "glazing_layers": 2, "gas_fill": "Argon", "frame_type": "Vinyl", "low_e_coating": True }, "triple_glazed_argon_low_e": { "name": "Triple glazed window with argon and low-e coating", "description": "Triple glazed window with argon fill, low-e coating, and vinyl frame", "u_value": 0.8, # W/(m²·K) "shgc": 0.3, # Solar Heat Gain Coefficient "vt": 0.6, # Visible Transmittance "glazing_layers": 3, "gas_fill": "Argon", "frame_type": "Vinyl", "low_e_coating": True } } def _load_door_types(self) -> Dict[str, Dict[str, Any]]: """ Load predefined door types from reference data. Returns: Dictionary of door types with properties """ return { "solid_wood_door": { "name": "Solid wood door", "description": "Solid wood door with no glazing", "u_value": 2.2, # W/(m²·K) "glazing_percentage": 0, "door_type": "Solid" }, "insulated_steel_door": { "name": "Insulated steel door", "description": "Insulated steel door with no glazing", "u_value": 1.2, # W/(m²·K) "glazing_percentage": 0, "door_type": "Solid" }, "partially_glazed_door": { "name": "Partially glazed door", "description": "Wood door with 25% glazing", "u_value": 2.8, # W/(m²·K) "glazing_percentage": 25, "door_type": "Partially glazed", "shgc": 0.76, # Solar Heat Gain Coefficient for the glazed portion "vt": 0.81 # Visible Transmittance for the glazed portion }, "glass_door": { "name": "Glass door", "description": "Full glass door with aluminum frame", "u_value": 3.8, # W/(m²·K) "glazing_percentage": 90, "door_type": "Glass", "shgc": 0.76, # Solar Heat Gain Coefficient "vt": 0.81 # Visible Transmittance } } def _load_internal_loads(self) -> Dict[str, Dict[str, Any]]: """ Load internal load data from reference data. Returns: Dictionary of internal load types with properties """ return { "occupancy": { "seated_very_light_work": { "name": "Seated, very light work", "sensible_heat": 70, # W per person "latent_heat": 45 # W per person }, "office_work_standing": { "name": "Office work, standing", "sensible_heat": 75, # W per person "latent_heat": 55 # W per person }, "light_physical_work": { "name": "Light physical work", "sensible_heat": 80, # W per person "latent_heat": 140 # W per person }, "medium_physical_work": { "name": "Medium physical work", "sensible_heat": 90, # W per person "latent_heat": 185 # W per person }, "heavy_physical_work": { "name": "Heavy physical work", "sensible_heat": 170, # W per person "latent_heat": 255 # W per person } }, "lighting": { "led": { "name": "LED", "power_density_range": [5, 10], # W/m² "heat_to_space": 0.9 # Fraction of power that becomes heat }, "fluorescent": { "name": "Fluorescent", "power_density_range": [10, 15], # W/m² "heat_to_space": 0.95 # Fraction of power that becomes heat }, "incandescent": { "name": "Incandescent", "power_density_range": [15, 25], # W/m² "heat_to_space": 0.98 # Fraction of power that becomes heat }, "halogen": { "name": "Halogen", "power_density_range": [12, 20], # W/m² "heat_to_space": 0.97 # Fraction of power that becomes heat } }, "equipment": { "office_equipment": { "name": "Office Equipment", "power_density_range": [10, 20], # W/m² "sensible_fraction": 0.9, "latent_fraction": 0.1 }, "kitchen_equipment": { "name": "Kitchen Equipment", "power_density_range": [30, 200], # W/m² "sensible_fraction": 0.6, "latent_fraction": 0.4 }, "manufacturing_equipment": { "name": "Manufacturing Equipment", "power_density_range": [20, 100], # W/m² "sensible_fraction": 0.8, "latent_fraction": 0.2 } } } def get_material(self, material_id: str) -> Optional[Dict[str, Any]]: """ Get material properties by ID. Args: material_id: Material identifier Returns: Dictionary of material properties or None if not found """ return self.materials.get(material_id) def get_wall_type(self, wall_type_id: str) -> Optional[Dict[str, Any]]: """ Get wall type properties by ID. Args: wall_type_id: Wall type identifier Returns: Dictionary of wall type properties or None if not found """ return self.wall_types.get(wall_type_id) def get_roof_type(self, roof_type_id: str) -> Optional[Dict[str, Any]]: """ Get roof type properties by ID. Args: roof_type_id: Roof type identifier Returns: Dictionary of roof type properties or None if not found """ return self.roof_types.get(roof_type_id) def get_floor_type(self, floor_type_id: str) -> Optional[Dict[str, Any]]: """ Get floor type properties by ID. Args: floor_type_id: Floor type identifier Returns: Dictionary of floor type properties or None if not found """ return self.floor_types.get(floor_type_id) def get_window_type(self, window_type_id: str) -> Optional[Dict[str, Any]]: """ Get window type properties by ID. Args: window_type_id: Window type identifier Returns: Dictionary of window type properties or None if not found """ return self.window_types.get(window_type_id) def get_door_type(self, door_type_id: str) -> Optional[Dict[str, Any]]: """ Get door type properties by ID. Args: door_type_id: Door type identifier Returns: Dictionary of door type properties or None if not found """ return self.door_types.get(door_type_id) def get_internal_load(self, load_type: str, load_id: str) -> Optional[Dict[str, Any]]: """ Get internal load properties by type and ID. Args: load_type: Type of internal load (occupancy, lighting, equipment) load_id: Internal load identifier Returns: Dictionary of internal load properties or None if not found """ if load_type in self.internal_loads: return self.internal_loads[load_type].get(load_id) return None 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 """ 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) @classmethod def from_json(cls, file_path: str) -> 'ReferenceData': """ Create a ReferenceData instance from a JSON file. Args: file_path: Path to the input JSON file Returns: A new ReferenceData instance """ with open(file_path, 'r') as f: data = json.load(f) ref_data = cls() ref_data.materials = data.get("materials", ref_data.materials) ref_data.wall_types = data.get("wall_types", ref_data.wall_types) ref_data.roof_types = data.get("roof_types", ref_data.roof_types) ref_data.floor_types = data.get("floor_types", ref_data.floor_types) ref_data.window_types = data.get("window_types", ref_data.window_types) ref_data.door_types = data.get("door_types", ref_data.door_types) ref_data.internal_loads = data.get("internal_loads", ref_data.internal_loads) return ref_data # Create a singleton instance reference_data = ReferenceData() # Export reference data to JSON if needed if __name__ == "__main__": reference_data.export_to_json(os.path.join(DATA_DIR, "reference_data.json"))