|
|
""" |
|
|
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() |
|
|
|
|
|
|
|
|
building_components = input_data.get('building_components', []) |
|
|
windows = input_data.get('windows', []) |
|
|
infiltration = input_data.get('infiltration', {}) |
|
|
internal_gains = input_data.get('internal_gains', {}) |
|
|
|
|
|
|
|
|
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() |
|
|
|
|
|
|
|
|
building_components = input_data.get('building_components', []) |
|
|
infiltration = input_data.get('infiltration', {}) |
|
|
|
|
|
|
|
|
results = calculator.calculate_total_heating_load( |
|
|
building_components=building_components, |
|
|
infiltration=infiltration |
|
|
) |
|
|
|
|
|
|
|
|
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 |
|
|
) |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
registry = CalculationMethodRegistry() |
|
|
|
|
|
|
|
|
registry.register_method('ashrae_cooling', ASHRAECoolingMethod) |
|
|
registry.register_method('ashrae_heating', ASHRAEHeatingMethod) |
|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
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) |
|
|
""" |
|
|
|