HVAC / calculation_methods.py
mabuseif's picture
Upload 14 files
e61124a verified
"""
Calculation Method Interface for HVAC Load Calculator
This module defines the interface for calculation methods in the HVAC Load Calculator.
It provides a base class that all calculation methods should inherit from.
"""
from abc import ABC, abstractmethod
class CalculationMethod(ABC):
"""
Abstract base class for HVAC load calculation methods.
All calculation methods should inherit from this class and implement
the required methods.
"""
@property
@abstractmethod
def name(self):
"""
Get the name of the calculation method.
Returns:
str: Name of the calculation method
"""
pass
@property
@abstractmethod
def description(self):
"""
Get the description of the calculation method.
Returns:
str: Description of the calculation method
"""
pass
@property
@abstractmethod
def version(self):
"""
Get the version of the calculation method.
Returns:
str: Version of the calculation method
"""
pass
@abstractmethod
def calculate(self, input_data):
"""
Perform the calculation.
Args:
input_data (dict): Input data for the calculation
Returns:
dict: Calculation results
"""
pass
@abstractmethod
def get_input_schema(self):
"""
Get the input schema for the calculation method.
Returns:
dict: JSON schema for input validation
"""
pass
@abstractmethod
def get_output_schema(self):
"""
Get the output schema for the calculation method.
Returns:
dict: JSON schema for output validation
"""
pass
class ASHRAECoolingMethod(CalculationMethod):
"""
ASHRAE method for cooling load calculation.
"""
@property
def name(self):
return "ASHRAE Cooling Load Method"
@property
def description(self):
return "Calculates cooling loads using the ASHRAE method for residential buildings."
@property
def version(self):
return "1.0"
def calculate(self, input_data):
"""
Calculate cooling load using the ASHRAE method.
Args:
input_data (dict): Input data for the calculation
Returns:
dict: Calculation results
"""
from cooling_load import CoolingLoadCalculator
calculator = CoolingLoadCalculator()
# Extract input data
building_components = input_data.get('building_components', [])
windows = input_data.get('windows', [])
infiltration = input_data.get('infiltration', {})
internal_gains = input_data.get('internal_gains', {})
# Perform calculation
results = calculator.calculate_total_cooling_load(
building_components=building_components,
windows=windows,
infiltration=infiltration,
internal_gains=internal_gains
)
return results
def get_input_schema(self):
"""
Get the input schema for the ASHRAE cooling load method.
Returns:
dict: JSON schema for input validation
"""
return {
"type": "object",
"properties": {
"building_components": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"area": {"type": "number", "minimum": 0},
"u_value": {"type": "number", "minimum": 0},
"temp_diff": {"type": "number"}
},
"required": ["area", "u_value", "temp_diff"]
}
},
"windows": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"area": {"type": "number", "minimum": 0},
"u_value": {"type": "number", "minimum": 0},
"orientation": {"type": "string", "enum": ["north", "east", "south", "west", "horizontal"]},
"glass_type": {"type": "string"},
"shading": {"type": "string"},
"shade_factor": {"type": "number", "minimum": 0, "maximum": 1},
"temp_diff": {"type": "number"}
},
"required": ["area", "u_value", "orientation", "temp_diff"]
}
},
"infiltration": {
"type": "object",
"properties": {
"volume": {"type": "number", "minimum": 0},
"air_changes": {"type": "number", "minimum": 0},
"temp_diff": {"type": "number"}
},
"required": ["volume", "air_changes", "temp_diff"]
},
"internal_gains": {
"type": "object",
"properties": {
"num_people": {"type": "integer", "minimum": 0},
"has_kitchen": {"type": "boolean"},
"equipment_watts": {"type": "number", "minimum": 0}
},
"required": ["num_people"]
}
},
"required": ["building_components", "infiltration", "internal_gains"]
}
def get_output_schema(self):
"""
Get the output schema for the ASHRAE cooling load method.
Returns:
dict: JSON schema for output validation
"""
return {
"type": "object",
"properties": {
"conduction_gain": {"type": "number"},
"window_conduction_gain": {"type": "number"},
"window_solar_gain": {"type": "number"},
"infiltration_gain": {"type": "number"},
"internal_gain": {"type": "number"},
"sensible_load": {"type": "number"},
"latent_load": {"type": "number"},
"total_load": {"type": "number"}
},
"required": ["sensible_load", "latent_load", "total_load"]
}
class ASHRAEHeatingMethod(CalculationMethod):
"""
ASHRAE method for heating load calculation.
"""
@property
def name(self):
return "ASHRAE Heating Load Method"
@property
def description(self):
return "Calculates heating loads using the ASHRAE method for residential buildings."
@property
def version(self):
return "1.0"
def calculate(self, input_data):
"""
Calculate heating load using the ASHRAE method.
Args:
input_data (dict): Input data for the calculation
Returns:
dict: Calculation results
"""
from heating_load import HeatingLoadCalculator
calculator = HeatingLoadCalculator()
# Extract input data
building_components = input_data.get('building_components', [])
infiltration = input_data.get('infiltration', {})
# Perform calculation
results = calculator.calculate_total_heating_load(
building_components=building_components,
infiltration=infiltration
)
# Calculate annual heating requirement if location and occupancy data are provided
if 'location' in input_data and 'occupancy_type' in input_data:
location = input_data.get('location')
occupancy_type = input_data.get('occupancy_type')
base_temp = input_data.get('base_temp', 18)
annual_results = calculator.calculate_annual_heating_requirement(
results['total_load'],
location,
occupancy_type,
base_temp
)
# Combine results
results.update(annual_results)
return results
def get_input_schema(self):
"""
Get the input schema for the ASHRAE heating load method.
Returns:
dict: JSON schema for input validation
"""
return {
"type": "object",
"properties": {
"building_components": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"area": {"type": "number", "minimum": 0},
"u_value": {"type": "number", "minimum": 0},
"temp_diff": {"type": "number", "minimum": 0}
},
"required": ["area", "u_value", "temp_diff"]
}
},
"infiltration": {
"type": "object",
"properties": {
"volume": {"type": "number", "minimum": 0},
"air_changes": {"type": "number", "minimum": 0},
"temp_diff": {"type": "number", "minimum": 0}
},
"required": ["volume", "air_changes", "temp_diff"]
},
"location": {"type": "string"},
"occupancy_type": {"type": "string"},
"base_temp": {"type": "number"}
},
"required": ["building_components", "infiltration"]
}
def get_output_schema(self):
"""
Get the output schema for the ASHRAE heating load method.
Returns:
dict: JSON schema for output validation
"""
return {
"type": "object",
"properties": {
"component_losses": {
"type": "object",
"additionalProperties": {"type": "number"}
},
"total_conduction_loss": {"type": "number"},
"infiltration_loss": {"type": "number"},
"total_load": {"type": "number"},
"heating_degree_days": {"type": "number"},
"correction_factor": {"type": "number"},
"annual_energy_kwh": {"type": "number"},
"annual_energy_mj": {"type": "number"}
},
"required": ["total_load"]
}
class CalculationMethodRegistry:
"""
Registry for calculation methods.
This class maintains a registry of available calculation methods
and provides methods to access them.
"""
def __init__(self):
"""Initialize the registry."""
self._methods = {}
def register_method(self, method_id, method_class):
"""
Register a calculation method.
Args:
method_id (str): Unique identifier for the method
method_class (type): Class implementing the CalculationMethod interface
Returns:
bool: True if registration was successful, False otherwise
"""
if method_id in self._methods:
return False
if not issubclass(method_class, CalculationMethod):
return False
self._methods[method_id] = method_class
return True
def get_method(self, method_id):
"""
Get a calculation method by ID.
Args:
method_id (str): Unique identifier for the method
Returns:
CalculationMethod: Instance of the calculation method, or None if not found
"""
if method_id not in self._methods:
return None
return self._methods[method_id]()
def get_available_methods(self):
"""
Get a list of available calculation methods.
Returns:
list: List of dictionaries with method information
"""
methods = []
for method_id, method_class in self._methods.items():
method = method_class()
methods.append({
'id': method_id,
'name': method.name,
'description': method.description,
'version': method.version
})
return methods
# Create a global registry instance
registry = CalculationMethodRegistry()
# Register the built-in calculation methods
registry.register_method('ashrae_cooling', ASHRAECoolingMethod)
registry.register_method('ashrae_heating', ASHRAEHeatingMethod)
# Example of how to add a new calculation method
"""
class CustomCoolingMethod(CalculationMethod):
@property
def name(self):
return "Custom Cooling Method"
@property
def description(self):
return "A custom method for calculating cooling loads."
@property
def version(self):
return "1.0"
def calculate(self, input_data):
# Custom calculation logic
pass
def get_input_schema(self):
# Custom input schema
pass
def get_output_schema(self):
# Custom output schema
pass
# Register the custom method
registry.register_method('custom_cooling', CustomCoolingMethod)
"""