Spaces:
Sleeping
Sleeping
""" | |
Reference Data Module for HVAC Load Calculator | |
This module provides reference data for materials, locations, and other parameters | |
needed for HVAC load calculations. | |
""" | |
import pandas as pd | |
import json | |
from pathlib import Path | |
class ReferenceData: | |
""" | |
A class to manage reference data for HVAC load calculations. | |
""" | |
def __init__(self): | |
"""Initialize the reference data.""" | |
self.materials = self._load_materials() | |
self.locations = self._load_locations() | |
self.glass_types = self._load_glass_types() | |
self.shading_factors = self._load_shading_factors() | |
self.internal_loads = self._load_internal_loads() | |
self.occupancy_factors = self._load_occupancy_factors() | |
def _load_materials(self): | |
""" | |
Load building material properties. | |
Returns: | |
dict: Dictionary of material properties | |
""" | |
# This would typically load from a JSON or CSV file | |
# For now, we'll define it directly | |
materials = { | |
"walls": { | |
"brick_veneer": { | |
"name": "Brick veneer with insulation", | |
"u_value": 0.5, # W/m²°C | |
"r_value": 2.0, # m²°C/W | |
"description": "Brick veneer with timber frame and insulation" | |
}, | |
"double_brick": { | |
"name": "Double brick", | |
"u_value": 1.88, # W/m²°C | |
"r_value": 0.53, # m²°C/W | |
"description": "Double brick wall without insulation" | |
}, | |
"double_brick_insulated": { | |
"name": "Double brick with insulation", | |
"u_value": 0.6, # W/m²°C | |
"r_value": 1.67, # m²°C/W | |
"description": "Double brick wall with insulation" | |
}, | |
"timber_frame": { | |
"name": "Timber frame", | |
"u_value": 0.8, # W/m²°C | |
"r_value": 1.25, # m²°C/W | |
"description": "Timber frame wall with insulation" | |
}, | |
"concrete_block": { | |
"name": "Concrete block", | |
"u_value": 2.3, # W/m²°C | |
"r_value": 0.43, # m²°C/W | |
"description": "Concrete block wall without insulation" | |
}, | |
"concrete_block_insulated": { | |
"name": "Concrete block with insulation", | |
"u_value": 0.7, # W/m²°C | |
"r_value": 1.43, # m²°C/W | |
"description": "Concrete block wall with insulation" | |
} | |
}, | |
"roofs": { | |
"metal_deck_insulated": { | |
"name": "Metal deck with insulation", | |
"u_value": 0.46, # W/m²°C | |
"r_value": 2.17, # m²°C/W | |
"description": "Metal deck roof with insulation and plasterboard ceiling" | |
}, | |
"metal_deck_uninsulated": { | |
"name": "Metal deck without insulation", | |
"u_value": 2.2, # W/m²°C | |
"r_value": 0.45, # m²°C/W | |
"description": "Metal deck roof without insulation" | |
}, | |
"concrete_slab_roof": { | |
"name": "Concrete slab roof", | |
"u_value": 3.1, # W/m²°C | |
"r_value": 0.32, # m²°C/W | |
"description": "Concrete slab roof without insulation" | |
}, | |
"concrete_slab_insulated": { | |
"name": "Concrete slab roof with insulation", | |
"u_value": 0.5, # W/m²°C | |
"r_value": 2.0, # m²°C/W | |
"description": "Concrete slab roof with insulation" | |
}, | |
"tiled_roof_insulated": { | |
"name": "Tiled roof with insulation", | |
"u_value": 0.4, # W/m²°C | |
"r_value": 2.5, # m²°C/W | |
"description": "Tiled roof with insulation and plasterboard ceiling" | |
}, | |
"tiled_roof_uninsulated": { | |
"name": "Tiled roof without insulation", | |
"u_value": 2.0, # W/m²°C | |
"r_value": 0.5, # m²°C/W | |
"description": "Tiled roof without insulation" | |
} | |
}, | |
"floors": { | |
"concrete_slab_ground": { | |
"name": "Concrete slab on ground", | |
"u_value": 0.6, # W/m²°C | |
"r_value": 1.67, # m²°C/W | |
"description": "Concrete slab directly on ground" | |
}, | |
"concrete_slab_insulated": { | |
"name": "Concrete slab with insulation", | |
"u_value": 0.3, # W/m²°C | |
"r_value": 3.33, # m²°C/W | |
"description": "Concrete slab with insulation" | |
}, | |
"suspended_timber": { | |
"name": "Suspended timber floor", | |
"u_value": 1.5, # W/m²°C | |
"r_value": 0.67, # m²°C/W | |
"description": "Suspended timber floor without insulation" | |
}, | |
"suspended_timber_insulated": { | |
"name": "Suspended timber floor with insulation", | |
"u_value": 0.4, # W/m²°C | |
"r_value": 2.5, # m²°C/W | |
"description": "Suspended timber floor with insulation" | |
} | |
} | |
} | |
return materials | |
def _load_locations(self): | |
""" | |
Load climate data for different locations. | |
Returns: | |
dict: Dictionary of location climate data | |
""" | |
# This would typically load from a JSON or CSV file | |
# For now, we'll define it directly | |
locations = { | |
"sydney": { | |
"name": "Sydney", | |
"state": "NSW", | |
"summer_design_temp": 32.0, # °C | |
"winter_design_temp": 7.0, # °C | |
"daily_temp_range": "medium", # 8.5-14°C | |
"heating_degree_days": 740, # Base 18°C | |
"cooling_degree_days": 350, # Base 18°C | |
"latitude": -33.87, | |
"longitude": 151.21 | |
}, | |
"melbourne": { | |
"name": "Melbourne", | |
"state": "VIC", | |
"summer_design_temp": 35.0, # °C | |
"winter_design_temp": 4.0, # °C | |
"daily_temp_range": "medium", # 8.5-14°C | |
"heating_degree_days": 1400, # Base 18°C | |
"cooling_degree_days": 200, # Base 18°C | |
"latitude": -37.81, | |
"longitude": 144.96 | |
}, | |
"brisbane": { | |
"name": "Brisbane", | |
"state": "QLD", | |
"summer_design_temp": 32.0, # °C | |
"winter_design_temp": 9.0, # °C | |
"daily_temp_range": "medium", # 8.5-14°C | |
"heating_degree_days": 320, # Base 18°C | |
"cooling_degree_days": 750, # Base 18°C | |
"latitude": -27.47, | |
"longitude": 153.03 | |
}, | |
"perth": { | |
"name": "Perth", | |
"state": "WA", | |
"summer_design_temp": 37.0, # °C | |
"winter_design_temp": 7.0, # °C | |
"daily_temp_range": "high", # >14°C | |
"heating_degree_days": 760, # Base 18°C | |
"cooling_degree_days": 600, # Base 18°C | |
"latitude": -31.95, | |
"longitude": 115.86 | |
}, | |
"adelaide": { | |
"name": "Adelaide", | |
"state": "SA", | |
"summer_design_temp": 38.0, # °C | |
"winter_design_temp": 5.0, # °C | |
"daily_temp_range": "high", # >14°C | |
"heating_degree_days": 1100, # Base 18°C | |
"cooling_degree_days": 500, # Base 18°C | |
"latitude": -34.93, | |
"longitude": 138.60 | |
}, | |
"hobart": { | |
"name": "Hobart", | |
"state": "TAS", | |
"summer_design_temp": 28.0, # °C | |
"winter_design_temp": 2.0, # °C | |
"daily_temp_range": "medium", # 8.5-14°C | |
"heating_degree_days": 1800, # Base 18°C | |
"cooling_degree_days": 50, # Base 18°C | |
"latitude": -42.88, | |
"longitude": 147.33 | |
}, | |
"darwin": { | |
"name": "Darwin", | |
"state": "NT", | |
"summer_design_temp": 34.0, # °C | |
"winter_design_temp": 15.0, # °C | |
"daily_temp_range": "low", # <8.5°C | |
"heating_degree_days": 0, # Base 18°C | |
"cooling_degree_days": 3500, # Base 18°C | |
"latitude": -12.46, | |
"longitude": 130.84 | |
}, | |
"canberra": { | |
"name": "Canberra", | |
"state": "ACT", | |
"summer_design_temp": 35.0, # °C | |
"winter_design_temp": -1.0, # °C | |
"daily_temp_range": "high", # >14°C | |
"heating_degree_days": 2000, # Base 18°C | |
"cooling_degree_days": 150, # Base 18°C | |
"latitude": -35.28, | |
"longitude": 149.13 | |
}, | |
"mildura": { | |
"name": "Mildura", | |
"state": "VIC", | |
"summer_design_temp": 38.0, # °C | |
"winter_design_temp": 4.5, # °C | |
"daily_temp_range": "high", # >14°C | |
"heating_degree_days": 1200, # Base 18°C | |
"cooling_degree_days": 700, # Base 18°C | |
"latitude": -34.21, | |
"longitude": 142.14 | |
} | |
} | |
return locations | |
def _load_glass_types(self): | |
""" | |
Load glass type properties. | |
Returns: | |
dict: Dictionary of glass type properties | |
""" | |
# This would typically load from a JSON or CSV file | |
# For now, we'll define it directly | |
glass_types = { | |
"single": { | |
"name": "Single glazing", | |
"u_value": 5.8, # W/m²°C | |
"shgc": 0.85, # Solar Heat Gain Coefficient | |
"description": "Standard single glazed window" | |
}, | |
"double": { | |
"name": "Double glazing", | |
"u_value": 2.9, # W/m²°C | |
"shgc": 0.75, # Solar Heat Gain Coefficient | |
"description": "Standard double glazed window" | |
}, | |
"low_e": { | |
"name": "Low-E double glazing", | |
"u_value": 1.8, # W/m²°C | |
"shgc": 0.65, # Solar Heat Gain Coefficient | |
"description": "Double glazed window with low-emissivity coating" | |
}, | |
"triple": { | |
"name": "Triple glazing", | |
"u_value": 1.2, # W/m²°C | |
"shgc": 0.6, # Solar Heat Gain Coefficient | |
"description": "Triple glazed window" | |
}, | |
"tinted": { | |
"name": "Tinted single glazing", | |
"u_value": 5.8, # W/m²°C | |
"shgc": 0.65, # Solar Heat Gain Coefficient | |
"description": "Single glazed window with tinting" | |
}, | |
"tinted_double": { | |
"name": "Tinted double glazing", | |
"u_value": 2.9, # W/m²°C | |
"shgc": 0.55, # Solar Heat Gain Coefficient | |
"description": "Double glazed window with tinting" | |
} | |
} | |
return glass_types | |
def _load_shading_factors(self): | |
""" | |
Load shading factors for different shading devices. | |
Returns: | |
dict: Dictionary of shading factors | |
""" | |
# This would typically load from a JSON or CSV file | |
# For now, we'll define it directly | |
shading_factors = { | |
"none": { | |
"name": "No shading", | |
"factor": 0.0, | |
"description": "No shading devices" | |
}, | |
"internal_blinds": { | |
"name": "Internal venetian blinds", | |
"factor": 0.4, | |
"description": "Internal venetian blinds" | |
}, | |
"internal_drapes": { | |
"name": "Internal drapes", | |
"factor": 0.3, | |
"description": "Internal drapes or curtains" | |
}, | |
"external_awning": { | |
"name": "External awning", | |
"factor": 0.7, | |
"description": "External awning" | |
}, | |
"external_shutters": { | |
"name": "External shutters", | |
"factor": 0.8, | |
"description": "External shutters" | |
}, | |
"eaves": { | |
"name": "Eaves or overhang", | |
"factor": 0.5, | |
"description": "Eaves or overhang" | |
}, | |
"pergola": { | |
"name": "Pergola with vegetation", | |
"factor": 0.6, | |
"description": "Pergola with vegetation" | |
} | |
} | |
return shading_factors | |
def _load_internal_loads(self): | |
""" | |
Load internal load data. | |
Returns: | |
dict: Dictionary of internal load data | |
""" | |
# This would typically load from a JSON or CSV file | |
# For now, we'll define it directly | |
internal_loads = { | |
"people": { | |
"seated_resting": { | |
"name": "Seated, resting", | |
"sensible_heat": 75, # W per person | |
"latent_heat": 30 # W per person | |
}, | |
"seated_light_work": { | |
"name": "Seated, light work", | |
"sensible_heat": 85, # W per person | |
"latent_heat": 40 # W per person | |
}, | |
"standing_light_work": { | |
"name": "Standing, light work", | |
"sensible_heat": 90, # W per person | |
"latent_heat": 50 # W per person | |
}, | |
"light_activity": { | |
"name": "Light activity", | |
"sensible_heat": 100, # W per person | |
"latent_heat": 60 # W per person | |
}, | |
"medium_activity": { | |
"name": "Medium activity", | |
"sensible_heat": 120, # W per person | |
"latent_heat": 80 # W per person | |
} | |
}, | |
"lighting": { | |
"incandescent": { | |
"name": "Incandescent", | |
"heat_factor": 1.0 # 100% of wattage becomes heat | |
}, | |
"fluorescent": { | |
"name": "Fluorescent", | |
"heat_factor": 1.2 # 120% of wattage becomes heat (includes ballast) | |
}, | |
"led": { | |
"name": "LED", | |
"heat_factor": 0.8 # 80% of wattage becomes heat | |
} | |
}, | |
"appliances": { | |
"kitchen": { | |
"name": "Kitchen", | |
"heat_gain": 1000 # W | |
}, | |
"living_room": { | |
"name": "Living room", | |
"heat_gain": 300 # W | |
}, | |
"bedroom": { | |
"name": "Bedroom", | |
"heat_gain": 150 # W | |
}, | |
"office": { | |
"name": "Home office", | |
"heat_gain": 450 # W | |
} | |
} | |
} | |
return internal_loads | |
def _load_occupancy_factors(self): | |
""" | |
Load occupancy correction factors. | |
Returns: | |
dict: Dictionary of occupancy correction factors | |
""" | |
# This would typically load from a JSON or CSV file | |
# For now, we'll define it directly | |
occupancy_factors = { | |
"continuous": { | |
"name": "Continuous", | |
"factor": 1.0, | |
"description": "Continuously heated" | |
}, | |
"intermittent": { | |
"name": "Intermittent", | |
"factor": 0.8, | |
"description": "Heated during occupied hours" | |
}, | |
"night_setback": { | |
"name": "Night setback", | |
"factor": 0.9, | |
"description": "Temperature setback at night" | |
}, | |
"weekend_off": { | |
"name": "Weekend off", | |
"factor": 0.85, | |
"description": "Heating off during weekends" | |
}, | |
"vacation_home": { | |
"name": "Vacation home", | |
"factor": 0.6, | |
"description": "Occasionally occupied" | |
} | |
} | |
return occupancy_factors | |
def get_material_by_type(self, material_type, material_id): | |
""" | |
Get material properties by type and ID. | |
Args: | |
material_type (str): Type of material ('walls', 'roofs', 'floors') | |
material_id (str): ID of the material | |
Returns: | |
dict: Material properties | |
""" | |
# Check if this is a custom material (custom_[type]) | |
if material_id == f"custom_{material_type}": | |
# Return the custom material from session state if available | |
import streamlit as st | |
if "custom_materials" in st.session_state and material_type in st.session_state.custom_materials: | |
return st.session_state.custom_materials[material_type] | |
# Return a default custom material template if not in session state | |
return { | |
"name": f"Custom {material_type[:-1]}", # Remove 's' from end | |
"u_value": 1.0, # Default U-value | |
"r_value": 1.0, # Default R-value | |
"description": f"Custom {material_type[:-1]} with user-defined properties" | |
} | |
# Return predefined material | |
if material_type in self.materials and material_id in self.materials[material_type]: | |
return self.materials[material_type][material_id] | |
return None | |
def get_location_data(self, location_id): | |
""" | |
Get climate data for a location. | |
Args: | |
location_id (str): ID of the location | |
Returns: | |
dict: Location climate data | |
""" | |
if location_id in self.locations: | |
return self.locations[location_id] | |
return None | |
def get_glass_type(self, glass_id): | |
""" | |
Get glass type properties. | |
Args: | |
glass_id (str): ID of the glass type | |
Returns: | |
dict: Glass type properties | |
""" | |
if glass_id in self.glass_types: | |
return self.glass_types[glass_id] | |
return None | |
def get_shading_factor(self, shading_id): | |
""" | |
Get shading factor. | |
Args: | |
shading_id (str): ID of the shading type | |
Returns: | |
dict: Shading factor data | |
""" | |
if shading_id in self.shading_factors: | |
return self.shading_factors[shading_id] | |
return None | |
def get_internal_load(self, load_type, load_id): | |
""" | |
Get internal load data. | |
Args: | |
load_type (str): Type of internal load ('people', 'lighting', 'appliances') | |
load_id (str): ID of the internal load | |
Returns: | |
dict: Internal load data | |
""" | |
if load_type in self.internal_loads and load_id in self.internal_loads[load_type]: | |
return self.internal_loads[load_type][load_id] | |
return None | |
def get_occupancy_factor(self, occupancy_id): | |
""" | |
Get occupancy correction factor. | |
Args: | |
occupancy_id (str): ID of the occupancy type | |
Returns: | |
dict: Occupancy correction factor data | |
""" | |
if occupancy_id in self.occupancy_factors: | |
return self.occupancy_factors[occupancy_id] | |
return None | |
def export_to_json(self, output_dir): | |
""" | |
Export all reference data to JSON files. | |
Args: | |
output_dir (str): Directory to save JSON files | |
Returns: | |
bool: True if successful, False otherwise | |
""" | |
try: | |
output_path = Path(output_dir) | |
output_path.mkdir(parents=True, exist_ok=True) | |
# Export materials | |
with open(output_path / "materials.json", "w") as f: | |
json.dump(self.materials, f, indent=2) | |
# Export locations | |
with open(output_path / "locations.json", "w") as f: | |
json.dump(self.locations, f, indent=2) | |
# Export glass types | |
with open(output_path / "glass_types.json", "w") as f: | |
json.dump(self.glass_types, f, indent=2) | |
# Export shading factors | |
with open(output_path / "shading_factors.json", "w") as f: | |
json.dump(self.shading_factors, f, indent=2) | |
# Export internal loads | |
with open(output_path / "internal_loads.json", "w") as f: | |
json.dump(self.internal_loads, f, indent=2) | |
# Export occupancy factors | |
with open(output_path / "occupancy_factors.json", "w") as f: | |
json.dump(self.occupancy_factors, f, indent=2) | |
return True | |
except Exception as e: | |
print(f"Error exporting reference data: {e}") | |
return False | |
# Example usage | |
if __name__ == "__main__": | |
ref_data = ReferenceData() | |
# Example: Get wall material properties | |
brick_veneer = ref_data.get_material_by_type("walls", "brick_veneer") | |
print("Brick Veneer Wall Properties:", brick_veneer) | |
# Example: Get location climate data | |
sydney_data = ref_data.get_location_data("sydney") | |
print("Sydney Climate Data:", sydney_data) | |
# Example: Export all data to JSON | |
ref_data.export_to_json("reference_data") | |