From 0d8572e94b4cfeacf59d3b6ecd93da41ccb07c17 Mon Sep 17 00:00:00 2001 From: majidrezaei93 Date: Wed, 4 Dec 2024 17:10:54 -0500 Subject: [PATCH] feat: add DHNNode, DHNEdge and DHNNetwork classes --- .../attributes/dhn_edge.py | 116 ++++++++++++++++++ .../attributes/dhn_node.py | 81 ++++++++++++ hub/city_model_structure/dhn_network.py | 48 ++++++++ 3 files changed, 245 insertions(+) create mode 100644 hub/city_model_structure/attributes/dhn_edge.py create mode 100644 hub/city_model_structure/attributes/dhn_node.py create mode 100644 hub/city_model_structure/dhn_network.py diff --git a/hub/city_model_structure/attributes/dhn_edge.py b/hub/city_model_structure/attributes/dhn_edge.py new file mode 100644 index 00000000..c0e7e226 --- /dev/null +++ b/hub/city_model_structure/attributes/dhn_edge.py @@ -0,0 +1,116 @@ +from typing import List, Dict, Union +from hub.city_model_structure.attributes.edge import Edge + + +class DHNEdge(Edge): + """ + District Heating Network Edge class, inherits from Edge. + """ + def __init__(self, name, nodes=None, length=0.0, diameter=0.0, nominal_diameter=0, + mass_flow_rate=None, roughness=0.0, pressure_drop=0.0): + super().__init__(name, nodes) + self._length = length + self._diameter = diameter + self._nominal_diameter = nominal_diameter + self._mass_flow_rate = mass_flow_rate if mass_flow_rate else {} # Initialize as empty dictionary + self._roughness = roughness + self._pressure_drop = pressure_drop + + @property + def length(self) -> float: + """ + Get length of the edge + :return: float + """ + return self._length + + @length.setter + def length(self, value: Union[None, float]): + """ + Set length of the edge + :param value: float + """ + self._length = max(value or 0.0, 0.0) + + @property + def diameter(self) -> float: + """ + Get diameter of the edge + :return: float + """ + return self._diameter + + @diameter.setter + def diameter(self, value: Union[None, float]): + """ + Set diameter of the edge + :param value: float + """ + self._diameter = value if value and value > 0 else 0.1 # Default to 0.1 if invalid + + @property + def nominal_diameter(self) -> int: + """ + Get nominal diameter of the edge + :return: int + """ + return self._nominal_diameter + + @nominal_diameter.setter + def nominal_diameter(self, value: Union[None, int]): + """ + Set nominal diameter of the edge + :param value: int + """ + self._nominal_diameter = value if value and value > 0 else 1 # Default to 1 if invalid + + @property + def mass_flow_rate(self) -> Dict: + """ + Get mass flow rate data + :return: dict + """ + return self._mass_flow_rate + + @mass_flow_rate.setter + def mass_flow_rate(self, value: Union[None, Dict]): + """ + Set mass flow rate data + :param value: dict + """ + if value and isinstance(value, dict): + self._mass_flow_rate = value + else: + self._mass_flow_rate = {} # Default to empty dictionary + + @property + def roughness(self) -> float: + """ + Get roughness of the edge + :return: float + """ + return self._roughness + + @roughness.setter + def roughness(self, value: Union[None, float]): + """ + Set roughness of the edge + :param value: float + """ + self._roughness = max(value or 0.0, 0.0) + + @property + def pressure_drop(self) -> float: + """ + Get pressure drop across the edge + :return: float + """ + return self._pressure_drop + + @pressure_drop.setter + def pressure_drop(self, value: Union[None, float]): + """ + Set pressure drop across the edge + :param value: float + """ + self._pressure_drop = max(value or 0.0, 0.0) diff --git a/hub/city_model_structure/attributes/dhn_node.py b/hub/city_model_structure/attributes/dhn_node.py new file mode 100644 index 00000000..2d36e04e --- /dev/null +++ b/hub/city_model_structure/attributes/dhn_node.py @@ -0,0 +1,81 @@ +from typing import Union +from hub.city_model_structure.attributes.node import Node + + +class DHNNode(Node): + """ + District Heating Network Node class, inherits from Node. + """ + def __init__(self, name, edges=None, pos=(0, 0), heat_exchanger_resistance=0, building=None, valve_resistance=0): + super().__init__(name, edges) + self._pos = pos + self._heat_exchanger_resistance = heat_exchanger_resistance + self._building = building + self._valve_resistance = valve_resistance + + @property + def pos(self) -> tuple: + """ + Get the position of the node + :return: tuple + """ + return self._pos + + @pos.setter + def pos(self, value: Union[None, tuple]): + """ + Set the position of the node + :param value: tuple + """ + if value and isinstance(value, tuple) and len(value) == 2: + self._pos = value + else: + self._pos = (0, 0) # Default position + + @property + def heat_exchanger_resistance(self) -> int: + """ + Get heat exchanger resistance + :return: int + """ + return self._heat_exchanger_resistance + + @heat_exchanger_resistance.setter + def heat_exchanger_resistance(self, value: Union[None, int]): + """ + Set heat exchanger resistance + :param value: int + """ + self._heat_exchanger_resistance = max(value or 0, 0) + + @property + def building(self): + """ + Get the associated building + :return: object + """ + return self._building + + @building.setter + def building(self, value): + """ + Set the associated building + :param value: object + """ + self._building = value + + @property + def valve_resistance(self) -> int: + """ + Get valve resistance + :return: int + """ + return self._valve_resistance + + @valve_resistance.setter + def valve_resistance(self, value: Union[None, int]): + """ + Set valve resistance + :param value: int + """ + self._valve_resistance = max(value or 0, 0) diff --git a/hub/city_model_structure/dhn_network.py b/hub/city_model_structure/dhn_network.py new file mode 100644 index 00000000..adcb07f0 --- /dev/null +++ b/hub/city_model_structure/dhn_network.py @@ -0,0 +1,48 @@ +from hub.city_model_structure.network import Network +from typing import Union +from hub.city_model_structure.attributes.dhn_node import DHNNode +from hub.city_model_structure.attributes.dhn_edge import DHNEdge + + +class DHNNetwork(Network): + """ + District Heating Network class, inherits from Network. + """ + def __init__(self, name, edges=None, nodes=None): + super().__init__(name, edges, nodes) + + def add_node(self, node: DHNNode): + """ + Add a DHN node to the network + :param node: DHNNode + """ + self._nodes.append(node) + + def add_edge(self, edge: DHNEdge): + """ + Add a DHN edge to the network + :param edge: DHNEdge + """ + self._edges.append(edge) + + def find_node_by_name(self, name: str) -> Union[None, DHNNode]: + """ + Find a node in the network by name + :param name: str + :return: DHNNode or None + """ + for node in self._nodes: + if node.name == name: + return node + return None + + def find_edge_by_name(self, name: str) -> Union[None, DHNEdge]: + """ + Find an edge in the network by name + :param name: str + :return: DHNEdge or None + """ + for edge in self._edges: + if edge.name == name: + return edge + return None \ No newline at end of file