Spaces:
Sleeping
Sleeping
| """ | |
| ASHRAE Cooling Load Calculation Module | |
| This module implements the ASHRAE method for calculating cooling loads in residential buildings. | |
| It calculates the sensible cooling load and then applies a factor of 1.3 to account for latent load. | |
| """ | |
| import numpy as np | |
| import pandas as pd | |
| class CoolingLoadCalculator: | |
| """ | |
| A class to calculate cooling loads using the ASHRAE method. | |
| """ | |
| def __init__(self): | |
| """Initialize the cooling load calculator with default values.""" | |
| # Default values for internal heat gains (W) | |
| self.heat_gain_per_person = 75 | |
| self.heat_gain_kitchen = 1000 | |
| # Specific heat capacity of air × density of air | |
| self.air_heat_factor = 0.33 | |
| def calculate_conduction_heat_gain(self, area, u_value, temp_diff): | |
| """ | |
| Calculate conduction heat gain through building components. | |
| Args: | |
| area (float): Area of the building component in m² | |
| u_value (float): U-value of the component in W/m²°C | |
| temp_diff (float): Temperature difference (outside - inside) in °C | |
| Returns: | |
| float: Heat gain in Watts | |
| """ | |
| return area * u_value * temp_diff | |
| def calculate_wall_solar_heat_gain(self, area, u_value, orientation, daily_range='medium', latitude='medium'): | |
| """ | |
| Calculate solar heat gain through walls based on orientation. | |
| Args: | |
| area (float): Area of the wall in m² | |
| u_value (float): U-value of the wall in W/m²°C | |
| orientation (str): Wall orientation ('north', 'east', 'south', 'west') | |
| daily_range (str): Daily temperature range ('low', 'medium', 'high') | |
| latitude (str): Latitude category ('low', 'medium', 'high') | |
| Returns: | |
| float: Heat gain in Watts | |
| """ | |
| # Solar intensity factors based on orientation | |
| # These are simplified factors for demonstration | |
| orientation_factors = { | |
| 'north': 0.3, | |
| 'east': 0.7, | |
| 'south': 0.5, | |
| 'west': 0.8, | |
| 'horizontal': 1.0 | |
| } | |
| # Adjustments for latitude | |
| latitude_factors = { | |
| 'low': 1.1, # Closer to equator | |
| 'medium': 1.0, # Mid latitudes | |
| 'high': 0.9 # Closer to poles | |
| } | |
| # Adjustments for daily temperature range | |
| range_factors = { | |
| 'low': 0.95, # Less than 8.5°C | |
| 'medium': 1.0, # Between 8.5°C and 14°C | |
| 'high': 1.05 # Over 14°C | |
| } | |
| # Base solar heat gain through walls (W/m²) | |
| base_solar_gain = 15.0 | |
| # Get factors | |
| orientation_factor = orientation_factors.get(orientation.lower(), 0.5) # Default to south if not found | |
| latitude_factor = latitude_factors.get(latitude.lower(), 1.0) | |
| range_factor = range_factors.get(daily_range.lower(), 1.0) | |
| # Calculate solar heat gain | |
| solar_gain = area * base_solar_gain * orientation_factor * latitude_factor * range_factor | |
| # Factor in the U-value (walls with higher U-values transmit more solar heat) | |
| u_value_factor = min(u_value / 0.5, 2.0) # Normalize against a typical U-value of 0.5 | |
| return solar_gain * u_value_factor | |
| def calculate_solar_heat_gain(self, area, shgf, shade_factor=1.0): | |
| """ | |
| Calculate solar heat gain through glazing. | |
| Args: | |
| area (float): Area of the glazing in m² | |
| shgf (float): Solar Heat Gain Factor based on orientation and climate | |
| shade_factor (float): Factor to account for shading (1.0 = no shade, 0.0 = full shade) | |
| Returns: | |
| float: Heat gain in Watts | |
| """ | |
| return area * shgf * shade_factor | |
| def calculate_infiltration_heat_gain(self, volume, air_changes, temp_diff): | |
| """ | |
| Calculate heat gain due to infiltration and ventilation. | |
| Args: | |
| volume (float): Volume of the space in m³ | |
| air_changes (float): Number of air changes per hour | |
| temp_diff (float): Temperature difference (outside - inside) in °C | |
| Returns: | |
| float: Heat gain in Watts | |
| """ | |
| return self.air_heat_factor * volume * air_changes * temp_diff | |
| def calculate_internal_heat_gain(self, num_people, has_kitchen=False, equipment_watts=0): | |
| """ | |
| Calculate internal heat gain from people, kitchen, and equipment. | |
| Args: | |
| num_people (int): Number of occupants | |
| has_kitchen (bool): Whether the space includes a kitchen | |
| equipment_watts (float): Additional equipment heat gain in Watts | |
| Returns: | |
| float: Heat gain in Watts | |
| """ | |
| people_gain = num_people * self.heat_gain_per_person | |
| kitchen_gain = self.heat_gain_kitchen if has_kitchen else 0 | |
| return people_gain + kitchen_gain + equipment_watts | |
| def get_solar_heat_gain_factor(self, orientation, glass_type, daily_range, latitude='medium'): | |
| """ | |
| Get the Solar Heat Gain Factor based on orientation, glass type, and climate. | |
| Args: | |
| orientation (str): Window orientation ('north', 'east', 'south', 'west') | |
| glass_type (str): Type of glass ('single', 'double', 'low_e') | |
| daily_range (str): Daily temperature range ('low', 'medium', 'high') | |
| latitude (str): Latitude category ('low', 'medium', 'high') | |
| Returns: | |
| float: Solar Heat Gain Factor in W/m² | |
| """ | |
| # This is a simplified version - in a real implementation, this would use lookup tables | |
| # based on the ASHRAE data | |
| # Base values for single glass at medium latitude | |
| base_values = { | |
| 'north': 200, | |
| 'east': 550, | |
| 'south': 350, | |
| 'west': 550, | |
| 'horizontal': 650 | |
| } | |
| # Adjustments for glass type | |
| glass_factors = { | |
| 'single': 1.0, | |
| 'double': 0.85, | |
| 'low_e': 0.65 | |
| } | |
| # Adjustments for latitude | |
| latitude_factors = { | |
| 'low': 1.1, # Closer to equator | |
| 'medium': 1.0, # Mid latitudes | |
| 'high': 0.9 # Closer to poles | |
| } | |
| # Adjustments for daily temperature range | |
| range_factors = { | |
| 'low': 0.95, # Less than 8.5°C | |
| 'medium': 1.0, # Between 8.5°C and 14°C | |
| 'high': 1.05 # Over 14°C | |
| } | |
| # Calculate the adjusted SHGF | |
| base_value = base_values.get(orientation.lower(), 350) # Default to south if not found | |
| glass_factor = glass_factors.get(glass_type.lower(), 1.0) | |
| latitude_factor = latitude_factors.get(latitude.lower(), 1.0) | |
| range_factor = range_factors.get(daily_range.lower(), 1.0) | |
| return base_value * glass_factor * latitude_factor * range_factor | |
| def calculate_total_cooling_load(self, building_components, windows, infiltration, internal_gains): | |
| """ | |
| Calculate the total cooling load including latent load. | |
| Args: | |
| building_components (list): List of dicts with 'area', 'u_value', 'temp_diff', and 'orientation' for each component | |
| windows (list): List of dicts with 'area', 'orientation', 'glass_type', 'shading', etc. | |
| infiltration (dict): Dict with 'volume', 'air_changes', and 'temp_diff' | |
| internal_gains (dict): Dict with 'num_people', 'has_kitchen', and 'equipment_watts' | |
| Returns: | |
| dict: Dictionary with sensible load, latent load, and total cooling load in Watts | |
| """ | |
| # Calculate conduction heat gain through building components | |
| conduction_gain = 0 | |
| wall_solar_gain = 0 | |
| for comp in building_components: | |
| # Calculate conduction gain | |
| conduction_gain += self.calculate_conduction_heat_gain(comp['area'], comp['u_value'], comp['temp_diff']) | |
| # Calculate solar gain for walls based on orientation | |
| if 'orientation' in comp: | |
| daily_range = comp.get('daily_range', 'medium') | |
| latitude = comp.get('latitude', 'medium') | |
| wall_solar_gain += self.calculate_wall_solar_heat_gain( | |
| comp['area'], | |
| comp['u_value'], | |
| comp['orientation'], | |
| daily_range, | |
| latitude | |
| ) | |
| # Calculate solar and conduction heat gain through windows | |
| window_conduction_gain = 0 | |
| window_solar_gain = 0 | |
| for window in windows: | |
| # Conduction through glass | |
| window_conduction_gain += self.calculate_conduction_heat_gain( | |
| window['area'], window['u_value'], window['temp_diff'] | |
| ) | |
| # Solar radiation through glass | |
| shgf = self.get_solar_heat_gain_factor( | |
| window['orientation'], | |
| window['glass_type'], | |
| window.get('daily_range', 'medium'), | |
| window.get('latitude', 'medium') | |
| ) | |
| shading_value = window.get('shading', 0.0) | |
| if shading_value == 'none' or shading_value == '': | |
| shading_value = 0.0 | |
| shade_factor = 1.0 - float(shading_value) | |
| window_solar_gain += self.calculate_solar_heat_gain(window['area'], shgf, shade_factor) | |
| # Calculate infiltration heat gain | |
| infiltration_gain = self.calculate_infiltration_heat_gain( | |
| infiltration['volume'], infiltration['air_changes'], infiltration['temp_diff'] | |
| ) | |
| # Calculate internal heat gain | |
| internal_gain = self.calculate_internal_heat_gain( | |
| internal_gains['num_people'], | |
| internal_gains.get('has_kitchen', False), | |
| internal_gains.get('equipment_watts', 0) | |
| ) | |
| # Calculate sensible cooling load | |
| sensible_load = conduction_gain + window_conduction_gain + window_solar_gain + wall_solar_gain + infiltration_gain + internal_gain | |
| # Calculate total cooling load (including latent load) | |
| latent_load = sensible_load * 0.3 # 30% of sensible load for latent load | |
| total_load = sensible_load * 1.3 # Factor of 1.3 to account for latent load | |
| return { | |
| 'conduction_gain': conduction_gain, | |
| 'window_conduction_gain': window_conduction_gain, | |
| 'window_solar_gain': window_solar_gain, | |
| 'wall_solar_gain': wall_solar_gain, | |
| 'infiltration_gain': infiltration_gain, | |
| 'internal_gain': internal_gain, | |
| 'sensible_load': sensible_load, | |
| 'latent_load': latent_load, | |
| 'total_load': total_load | |
| } | |
| # Example usage | |
| if __name__ == "__main__": | |
| calculator = CoolingLoadCalculator() | |
| # Example data for a simple room | |
| building_components = [ | |
| {'area': 20, 'u_value': 0.6, 'temp_diff': 11}, # Floor | |
| {'area': 50, 'u_value': 1.88, 'temp_diff': 11}, # Walls | |
| {'area': 20, 'u_value': 0.46, 'temp_diff': 11} # Ceiling | |
| ] | |
| windows = [ | |
| {'area': 4, 'orientation': 'north', 'glass_type': 'single', 'u_value': 5.8, 'temp_diff': 11, 'shading': 0.5}, | |
| {'area': 4, 'orientation': 'east', 'glass_type': 'single', 'u_value': 5.8, 'temp_diff': 11, 'shading': 0.0}, | |
| {'area': 4, 'orientation': 'west', 'glass_type': 'single', 'u_value': 5.8, 'temp_diff': 11, 'shading': 0.0} | |
| ] | |
| infiltration = {'volume': 60, 'air_changes': 0.5, 'temp_diff': 11} | |
| internal_gains = {'num_people': 4, 'has_kitchen': True, 'equipment_watts': 500} | |
| result = calculator.calculate_total_cooling_load(building_components, windows, infiltration, internal_gains) | |
| print("Cooling Load Calculation Results:") | |
| for key, value in result.items(): | |
| print(f"{key}: {value:.2f} W") | |