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