HVAC / cooling_load.py
mabuseif's picture
Upload 13 files
a1d7129 verified
"""
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")