|
|
""" |
|
|
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 |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
materials = { |
|
|
"walls": { |
|
|
"brick_veneer": { |
|
|
"name": "Brick veneer with insulation", |
|
|
"u_value": 0.5, |
|
|
"r_value": 2.0, |
|
|
"description": "Brick veneer with timber frame and insulation" |
|
|
}, |
|
|
"double_brick": { |
|
|
"name": "Double brick", |
|
|
"u_value": 1.88, |
|
|
"r_value": 0.53, |
|
|
"description": "Double brick wall without insulation" |
|
|
}, |
|
|
"double_brick_insulated": { |
|
|
"name": "Double brick with insulation", |
|
|
"u_value": 0.6, |
|
|
"r_value": 1.67, |
|
|
"description": "Double brick wall with insulation" |
|
|
}, |
|
|
"timber_frame": { |
|
|
"name": "Timber frame", |
|
|
"u_value": 0.8, |
|
|
"r_value": 1.25, |
|
|
"description": "Timber frame wall with insulation" |
|
|
}, |
|
|
"concrete_block": { |
|
|
"name": "Concrete block", |
|
|
"u_value": 2.3, |
|
|
"r_value": 0.43, |
|
|
"description": "Concrete block wall without insulation" |
|
|
}, |
|
|
"concrete_block_insulated": { |
|
|
"name": "Concrete block with insulation", |
|
|
"u_value": 0.7, |
|
|
"r_value": 1.43, |
|
|
"description": "Concrete block wall with insulation" |
|
|
} |
|
|
}, |
|
|
"roofs": { |
|
|
"metal_deck_insulated": { |
|
|
"name": "Metal deck with insulation", |
|
|
"u_value": 0.46, |
|
|
"r_value": 2.17, |
|
|
"description": "Metal deck roof with insulation and plasterboard ceiling" |
|
|
}, |
|
|
"metal_deck_uninsulated": { |
|
|
"name": "Metal deck without insulation", |
|
|
"u_value": 2.2, |
|
|
"r_value": 0.45, |
|
|
"description": "Metal deck roof without insulation" |
|
|
}, |
|
|
"concrete_slab_roof": { |
|
|
"name": "Concrete slab roof", |
|
|
"u_value": 3.1, |
|
|
"r_value": 0.32, |
|
|
"description": "Concrete slab roof without insulation" |
|
|
}, |
|
|
"concrete_slab_insulated": { |
|
|
"name": "Concrete slab roof with insulation", |
|
|
"u_value": 0.5, |
|
|
"r_value": 2.0, |
|
|
"description": "Concrete slab roof with insulation" |
|
|
}, |
|
|
"tiled_roof_insulated": { |
|
|
"name": "Tiled roof with insulation", |
|
|
"u_value": 0.4, |
|
|
"r_value": 2.5, |
|
|
"description": "Tiled roof with insulation and plasterboard ceiling" |
|
|
}, |
|
|
"tiled_roof_uninsulated": { |
|
|
"name": "Tiled roof without insulation", |
|
|
"u_value": 2.0, |
|
|
"r_value": 0.5, |
|
|
"description": "Tiled roof without insulation" |
|
|
} |
|
|
}, |
|
|
"floors": { |
|
|
"concrete_slab_ground": { |
|
|
"name": "Concrete slab on ground", |
|
|
"u_value": 0.6, |
|
|
"r_value": 1.67, |
|
|
"description": "Concrete slab directly on ground" |
|
|
}, |
|
|
"concrete_slab_insulated": { |
|
|
"name": "Concrete slab with insulation", |
|
|
"u_value": 0.3, |
|
|
"r_value": 3.33, |
|
|
"description": "Concrete slab with insulation" |
|
|
}, |
|
|
"suspended_timber": { |
|
|
"name": "Suspended timber floor", |
|
|
"u_value": 1.5, |
|
|
"r_value": 0.67, |
|
|
"description": "Suspended timber floor without insulation" |
|
|
}, |
|
|
"suspended_timber_insulated": { |
|
|
"name": "Suspended timber floor with insulation", |
|
|
"u_value": 0.4, |
|
|
"r_value": 2.5, |
|
|
"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 |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
locations = { |
|
|
"sydney": { |
|
|
"name": "Sydney", |
|
|
"state": "NSW", |
|
|
"summer_design_temp": 32.0, |
|
|
"winter_design_temp": 7.0, |
|
|
"daily_temp_range": "medium", |
|
|
"heating_degree_days": 740, |
|
|
"cooling_degree_days": 350, |
|
|
"latitude": -33.87, |
|
|
"longitude": 151.21 |
|
|
}, |
|
|
"melbourne": { |
|
|
"name": "Melbourne", |
|
|
"state": "VIC", |
|
|
"summer_design_temp": 35.0, |
|
|
"winter_design_temp": 4.0, |
|
|
"daily_temp_range": "medium", |
|
|
"heating_degree_days": 1400, |
|
|
"cooling_degree_days": 200, |
|
|
"latitude": -37.81, |
|
|
"longitude": 144.96 |
|
|
}, |
|
|
"brisbane": { |
|
|
"name": "Brisbane", |
|
|
"state": "QLD", |
|
|
"summer_design_temp": 32.0, |
|
|
"winter_design_temp": 9.0, |
|
|
"daily_temp_range": "medium", |
|
|
"heating_degree_days": 320, |
|
|
"cooling_degree_days": 750, |
|
|
"latitude": -27.47, |
|
|
"longitude": 153.03 |
|
|
}, |
|
|
"perth": { |
|
|
"name": "Perth", |
|
|
"state": "WA", |
|
|
"summer_design_temp": 37.0, |
|
|
"winter_design_temp": 7.0, |
|
|
"daily_temp_range": "high", |
|
|
"heating_degree_days": 760, |
|
|
"cooling_degree_days": 600, |
|
|
"latitude": -31.95, |
|
|
"longitude": 115.86 |
|
|
}, |
|
|
"adelaide": { |
|
|
"name": "Adelaide", |
|
|
"state": "SA", |
|
|
"summer_design_temp": 38.0, |
|
|
"winter_design_temp": 5.0, |
|
|
"daily_temp_range": "high", |
|
|
"heating_degree_days": 1100, |
|
|
"cooling_degree_days": 500, |
|
|
"latitude": -34.93, |
|
|
"longitude": 138.60 |
|
|
}, |
|
|
"hobart": { |
|
|
"name": "Hobart", |
|
|
"state": "TAS", |
|
|
"summer_design_temp": 28.0, |
|
|
"winter_design_temp": 2.0, |
|
|
"daily_temp_range": "medium", |
|
|
"heating_degree_days": 1800, |
|
|
"cooling_degree_days": 50, |
|
|
"latitude": -42.88, |
|
|
"longitude": 147.33 |
|
|
}, |
|
|
"darwin": { |
|
|
"name": "Darwin", |
|
|
"state": "NT", |
|
|
"summer_design_temp": 34.0, |
|
|
"winter_design_temp": 15.0, |
|
|
"daily_temp_range": "low", |
|
|
"heating_degree_days": 0, |
|
|
"cooling_degree_days": 3500, |
|
|
"latitude": -12.46, |
|
|
"longitude": 130.84 |
|
|
}, |
|
|
"canberra": { |
|
|
"name": "Canberra", |
|
|
"state": "ACT", |
|
|
"summer_design_temp": 35.0, |
|
|
"winter_design_temp": -1.0, |
|
|
"daily_temp_range": "high", |
|
|
"heating_degree_days": 2000, |
|
|
"cooling_degree_days": 150, |
|
|
"latitude": -35.28, |
|
|
"longitude": 149.13 |
|
|
}, |
|
|
"mildura": { |
|
|
"name": "Mildura", |
|
|
"state": "VIC", |
|
|
"summer_design_temp": 38.0, |
|
|
"winter_design_temp": 4.5, |
|
|
"daily_temp_range": "high", |
|
|
"heating_degree_days": 1200, |
|
|
"cooling_degree_days": 700, |
|
|
"latitude": -34.21, |
|
|
"longitude": 142.14 |
|
|
} |
|
|
} |
|
|
|
|
|
return locations |
|
|
|
|
|
def _load_glass_types(self): |
|
|
""" |
|
|
Load glass type properties. |
|
|
|
|
|
Returns: |
|
|
dict: Dictionary of glass type properties |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
glass_types = { |
|
|
"single": { |
|
|
"name": "Single glazing", |
|
|
"u_value": 5.8, |
|
|
"shgc": 0.85, |
|
|
"description": "Standard single glazed window" |
|
|
}, |
|
|
"double": { |
|
|
"name": "Double glazing", |
|
|
"u_value": 2.9, |
|
|
"shgc": 0.75, |
|
|
"description": "Standard double glazed window" |
|
|
}, |
|
|
"low_e": { |
|
|
"name": "Low-E double glazing", |
|
|
"u_value": 1.8, |
|
|
"shgc": 0.65, |
|
|
"description": "Double glazed window with low-emissivity coating" |
|
|
}, |
|
|
"triple": { |
|
|
"name": "Triple glazing", |
|
|
"u_value": 1.2, |
|
|
"shgc": 0.6, |
|
|
"description": "Triple glazed window" |
|
|
}, |
|
|
"tinted": { |
|
|
"name": "Tinted single glazing", |
|
|
"u_value": 5.8, |
|
|
"shgc": 0.65, |
|
|
"description": "Single glazed window with tinting" |
|
|
}, |
|
|
"tinted_double": { |
|
|
"name": "Tinted double glazing", |
|
|
"u_value": 2.9, |
|
|
"shgc": 0.55, |
|
|
"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 |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
internal_loads = { |
|
|
"people": { |
|
|
"seated_resting": { |
|
|
"name": "Seated, resting", |
|
|
"sensible_heat": 75, |
|
|
"latent_heat": 30 |
|
|
}, |
|
|
"seated_light_work": { |
|
|
"name": "Seated, light work", |
|
|
"sensible_heat": 85, |
|
|
"latent_heat": 40 |
|
|
}, |
|
|
"standing_light_work": { |
|
|
"name": "Standing, light work", |
|
|
"sensible_heat": 90, |
|
|
"latent_heat": 50 |
|
|
}, |
|
|
"light_activity": { |
|
|
"name": "Light activity", |
|
|
"sensible_heat": 100, |
|
|
"latent_heat": 60 |
|
|
}, |
|
|
"medium_activity": { |
|
|
"name": "Medium activity", |
|
|
"sensible_heat": 120, |
|
|
"latent_heat": 80 |
|
|
} |
|
|
}, |
|
|
"lighting": { |
|
|
"incandescent": { |
|
|
"name": "Incandescent", |
|
|
"heat_factor": 1.0 |
|
|
}, |
|
|
"fluorescent": { |
|
|
"name": "Fluorescent", |
|
|
"heat_factor": 1.2 |
|
|
}, |
|
|
"led": { |
|
|
"name": "LED", |
|
|
"heat_factor": 0.8 |
|
|
} |
|
|
}, |
|
|
"appliances": { |
|
|
"kitchen": { |
|
|
"name": "Kitchen", |
|
|
"heat_gain": 1000 |
|
|
}, |
|
|
"living_room": { |
|
|
"name": "Living room", |
|
|
"heat_gain": 300 |
|
|
}, |
|
|
"bedroom": { |
|
|
"name": "Bedroom", |
|
|
"heat_gain": 150 |
|
|
}, |
|
|
"office": { |
|
|
"name": "Home office", |
|
|
"heat_gain": 450 |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return internal_loads |
|
|
|
|
|
def _load_occupancy_factors(self): |
|
|
""" |
|
|
Load occupancy correction factors. |
|
|
|
|
|
Returns: |
|
|
dict: Dictionary of occupancy correction factors |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
""" |
|
|
|
|
|
if material_id == f"custom_{material_type}": |
|
|
|
|
|
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 { |
|
|
"name": f"Custom {material_type[:-1]}", |
|
|
"u_value": 1.0, |
|
|
"r_value": 1.0, |
|
|
"description": f"Custom {material_type[:-1]} with user-defined properties" |
|
|
} |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
with open(output_path / "materials.json", "w") as f: |
|
|
json.dump(self.materials, f, indent=2) |
|
|
|
|
|
|
|
|
with open(output_path / "locations.json", "w") as f: |
|
|
json.dump(self.locations, f, indent=2) |
|
|
|
|
|
|
|
|
with open(output_path / "glass_types.json", "w") as f: |
|
|
json.dump(self.glass_types, f, indent=2) |
|
|
|
|
|
|
|
|
with open(output_path / "shading_factors.json", "w") as f: |
|
|
json.dump(self.shading_factors, f, indent=2) |
|
|
|
|
|
|
|
|
with open(output_path / "internal_loads.json", "w") as f: |
|
|
json.dump(self.internal_loads, f, indent=2) |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
ref_data = ReferenceData() |
|
|
|
|
|
|
|
|
brick_veneer = ref_data.get_material_by_type("walls", "brick_veneer") |
|
|
print("Brick Veneer Wall Properties:", brick_veneer) |
|
|
|
|
|
|
|
|
sydney_data = ref_data.get_location_data("sydney") |
|
|
print("Sydney Climate Data:", sydney_data) |
|
|
|
|
|
|
|
|
ref_data.export_to_json("reference_data") |
|
|
|