Compare commits
1 Commits
main
...
feature/di
Author | SHA1 | Date | |
---|---|---|---|
0d8572e94b |
116
hub/city_model_structure/attributes/dhn_edge.py
Normal file
116
hub/city_model_structure/attributes/dhn_edge.py
Normal file
@ -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)
|
81
hub/city_model_structure/attributes/dhn_node.py
Normal file
81
hub/city_model_structure/attributes/dhn_node.py
Normal file
@ -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)
|
48
hub/city_model_structure/dhn_network.py
Normal file
48
hub/city_model_structure/dhn_network.py
Normal file
@ -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
|
@ -10,6 +10,7 @@ import copy
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
import hub.exports.building_energy.idf_helper as idf_cte
|
import hub.exports.building_energy.idf_helper as idf_cte
|
||||||
import hub.helpers.constants as cte
|
import hub.helpers.constants as cte
|
||||||
@ -47,6 +48,7 @@ class CercIdf(IdfBase):
|
|||||||
_thermostat_added_to_idf = {}
|
_thermostat_added_to_idf = {}
|
||||||
|
|
||||||
def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path, target_buildings=None):
|
def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path, target_buildings=None):
|
||||||
|
self._start = datetime.now()
|
||||||
super().__init__(city, output_path, idf_file_path, idd_file_path, epw_file_path, target_buildings)
|
super().__init__(city, output_path, idf_file_path, idd_file_path, epw_file_path, target_buildings)
|
||||||
self._add_surfaces = IdfSurfaces.add
|
self._add_surfaces = IdfSurfaces.add
|
||||||
self._add_file_schedule = IdfFileSchedule.add
|
self._add_file_schedule = IdfFileSchedule.add
|
||||||
@ -231,6 +233,7 @@ class CercIdf(IdfBase):
|
|||||||
# Merge files
|
# Merge files
|
||||||
self._merge_files()
|
self._merge_files()
|
||||||
self._add_outputs()
|
self._add_outputs()
|
||||||
|
print(f'{len(self._city.buildings)} buildings export completed in: {datetime.now() - self._start}')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _energy_plus(self):
|
def _energy_plus(self):
|
||||||
@ -245,4 +248,5 @@ class CercIdf(IdfBase):
|
|||||||
'--readvars',
|
'--readvars',
|
||||||
'--output-prefix', f'{self._city.name}_',
|
'--output-prefix', f'{self._city.name}_',
|
||||||
self._output_file_path]
|
self._output_file_path]
|
||||||
|
print(cmd)
|
||||||
subprocess.run(cmd, cwd=self._output_path)
|
subprocess.run(cmd, cwd=self._output_path)
|
||||||
|
@ -8,12 +8,10 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
|
|||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import shutil
|
import glob
|
||||||
import subprocess
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from geomeppy import IDF
|
from geomeppy import IDF
|
||||||
|
|
||||||
import hub.helpers.constants as cte
|
import hub.helpers.constants as cte
|
||||||
from hub.city_model_structure.attributes.schedule import Schedule
|
from hub.city_model_structure.attributes.schedule import Schedule
|
||||||
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
|
from hub.city_model_structure.building_demand.thermal_zone import ThermalZone
|
||||||
@ -531,7 +529,6 @@ class Idf:
|
|||||||
self._remove_sizing_periods()
|
self._remove_sizing_periods()
|
||||||
self._rename_building(self._city.name)
|
self._rename_building(self._city.name)
|
||||||
self._lod = self._city.level_of_detail.geometry
|
self._lod = self._city.level_of_detail.geometry
|
||||||
is_target = False
|
|
||||||
for building in self._city.buildings:
|
for building in self._city.buildings:
|
||||||
is_target = building.name in self._target_buildings or building.name in self._adjacent_buildings
|
is_target = building.name in self._target_buildings or building.name in self._adjacent_buildings
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
@ -659,20 +656,12 @@ class Idf:
|
|||||||
self._add_surfaces(building, building.name)
|
self._add_surfaces(building, building.name)
|
||||||
return self._idf
|
return self._idf
|
||||||
|
|
||||||
@property
|
|
||||||
def _energy_plus(self):
|
|
||||||
return shutil.which('energyplus')
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
cmd = [self._energy_plus,
|
"""
|
||||||
'--weather', self._epw_file_path,
|
Start the energy plus simulation
|
||||||
'--output-directory', self._output_path,
|
"""
|
||||||
'--idd', self._idd_file_path,
|
self._idf.run(expandobjects=False, readvars=True, output_directory=self._output_path,
|
||||||
'--expandobjects',
|
output_prefix=f'{self._city.name}_')
|
||||||
'--readvars',
|
|
||||||
'--output-prefix', f'{self._city.name}_',
|
|
||||||
self._idf_file_path]
|
|
||||||
subprocess.run(cmd, cwd=self._output_path)
|
|
||||||
|
|
||||||
def _add_block(self, building):
|
def _add_block(self, building):
|
||||||
_points = self._matrix_to_2d_list(building.foot_print.coordinates)
|
_points = self._matrix_to_2d_list(building.foot_print.coordinates)
|
||||||
|
@ -20,7 +20,7 @@ class EnergyPlus:
|
|||||||
header_parts = header.split(':')
|
header_parts = header.split(':')
|
||||||
building_name = header_parts[0]
|
building_name = header_parts[0]
|
||||||
variable = ':'.join(header_parts[1:]).strip() # concat the rest and ensure that : it's reintroduced just in case
|
variable = ':'.join(header_parts[1:]).strip() # concat the rest and ensure that : it's reintroduced just in case
|
||||||
if variable == '':
|
if variable is '':
|
||||||
continue
|
continue
|
||||||
if building_name not in self._summary_variables:
|
if building_name not in self._summary_variables:
|
||||||
self._building_energy_demands[variable] = [] # initialize the list of variables
|
self._building_energy_demands[variable] = [] # initialize the list of variables
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
"""
|
"""
|
||||||
Hub version number
|
Hub version number
|
||||||
"""
|
"""
|
||||||
__version__ = '0.3.0.5'
|
__version__ = '0.3.0.3'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
xmltodict
|
xmltodict
|
||||||
numpy
|
numpy==1.26.4
|
||||||
trimesh[all]
|
trimesh[all]
|
||||||
pyproj
|
pyproj
|
||||||
pandas
|
pandas
|
||||||
|
1
setup.py
1
setup.py
@ -59,7 +59,6 @@ setup(
|
|||||||
'hub.exports',
|
'hub.exports',
|
||||||
'hub.exports.building_energy',
|
'hub.exports.building_energy',
|
||||||
'hub.exports.building_energy.idf_files',
|
'hub.exports.building_energy.idf_files',
|
||||||
'hub.exports.building_energy.idf_helper',
|
|
||||||
'hub.exports.building_energy.insel',
|
'hub.exports.building_energy.insel',
|
||||||
'hub.exports.energy_systems',
|
'hub.exports.energy_systems',
|
||||||
'hub.exports.formats',
|
'hub.exports.formats',
|
||||||
|
@ -144,8 +144,7 @@ class TestExports(TestCase):
|
|||||||
UsageFactory('nrcan', city).enrich()
|
UsageFactory('nrcan', city).enrich()
|
||||||
WeatherFactory('epw', city).enrich()
|
WeatherFactory('epw', city).enrich()
|
||||||
try:
|
try:
|
||||||
_idf = EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
idf = EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||||
_idf.run()
|
|
||||||
except Exception:
|
except Exception:
|
||||||
self.fail("Idf ExportsFactory raised ExceptionType unexpectedly!")
|
self.fail("Idf ExportsFactory raised ExceptionType unexpectedly!")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user