epyt-flow 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- epyt_flow/EPANET/compile_macos.sh +4 -0
- epyt_flow/VERSION +1 -1
- epyt_flow/__init__.py +6 -2
- epyt_flow/data/benchmarks/leakdb.py +7 -12
- epyt_flow/data/networks.py +404 -40
- epyt_flow/rest_api/base_handler.py +14 -0
- epyt_flow/rest_api/scada_data/handlers.py +42 -0
- epyt_flow/rest_api/server.py +3 -1
- epyt_flow/simulation/events/leakages.py +27 -17
- epyt_flow/simulation/scada/scada_data.py +543 -12
- epyt_flow/simulation/scada/scada_data_export.py +38 -5
- epyt_flow/simulation/scenario_config.py +2 -2
- epyt_flow/simulation/scenario_simulator.py +44 -35
- epyt_flow/simulation/sensor_config.py +342 -47
- epyt_flow/topology.py +104 -4
- {epyt_flow-0.2.0.dist-info → epyt_flow-0.3.0.dist-info}/METADATA +17 -6
- {epyt_flow-0.2.0.dist-info → epyt_flow-0.3.0.dist-info}/RECORD +20 -19
- {epyt_flow-0.2.0.dist-info → epyt_flow-0.3.0.dist-info}/LICENSE +0 -0
- {epyt_flow-0.2.0.dist-info → epyt_flow-0.3.0.dist-info}/WHEEL +0 -0
- {epyt_flow-0.2.0.dist-info → epyt_flow-0.3.0.dist-info}/top_level.txt +0 -0
|
@@ -415,8 +415,8 @@ class ScenarioConfig(Serializable):
|
|
|
415
415
|
general_params["demand_model"] = general_settings["demand_model"]
|
|
416
416
|
if "quality_model" in general_settings.keys():
|
|
417
417
|
general_params["quality_model"] = general_settings["quality_model"]
|
|
418
|
-
if "
|
|
419
|
-
general_params["
|
|
418
|
+
if "flow_units_id" in general_settings.keys():
|
|
419
|
+
general_params["flow_units_id"] = general_settings["flow_units_id"]
|
|
420
420
|
|
|
421
421
|
sensor_config = data["sensors"]
|
|
422
422
|
|
|
@@ -17,8 +17,8 @@ from epyt.epanet import ToolkitConstants
|
|
|
17
17
|
from tqdm import tqdm
|
|
18
18
|
|
|
19
19
|
from .scenario_config import ScenarioConfig
|
|
20
|
-
from .sensor_config import SensorConfig, areaunit_to_id, massunit_to_id,
|
|
21
|
-
|
|
20
|
+
from .sensor_config import SensorConfig, areaunit_to_id, massunit_to_id, qualityunit_to_id, \
|
|
21
|
+
qualityunit_to_str, MASS_UNIT_MG, \
|
|
22
22
|
SENSOR_TYPE_LINK_FLOW, SENSOR_TYPE_LINK_QUALITY, SENSOR_TYPE_NODE_DEMAND, \
|
|
23
23
|
SENSOR_TYPE_NODE_PRESSURE, SENSOR_TYPE_NODE_QUALITY, \
|
|
24
24
|
SENSOR_TYPE_PUMP_STATE, SENSOR_TYPE_TANK_VOLUME, SENSOR_TYPE_VALVE_STATE, \
|
|
@@ -137,7 +137,7 @@ class ScenarioSimulator():
|
|
|
137
137
|
tank_id_to_idx: dict = None, bulkspecies_id_to_idx: dict = None,
|
|
138
138
|
surfacespecies_id_to_idx: dict = None) -> SensorConfig:
|
|
139
139
|
flow_unit = self.epanet_api.api.ENgetflowunits()
|
|
140
|
-
quality_unit =
|
|
140
|
+
quality_unit = qualityunit_to_id(self.epanet_api.getQualityInfo().QualityChemUnits)
|
|
141
141
|
bulk_species = []
|
|
142
142
|
surface_species = []
|
|
143
143
|
bulk_species_mass_unit = []
|
|
@@ -691,7 +691,7 @@ class ScenarioSimulator():
|
|
|
691
691
|
return {"code": qual_info.QualityCode,
|
|
692
692
|
"type": qual_info.QualityType,
|
|
693
693
|
"chemical_name": qual_info.QualityChemName,
|
|
694
|
-
"units":
|
|
694
|
+
"units": qualityunit_to_id(qual_info.QualityChemUnits),
|
|
695
695
|
"trace_node_id": qual_info.TraceNode}
|
|
696
696
|
|
|
697
697
|
def get_scenario_config(self) -> ScenarioConfig:
|
|
@@ -761,6 +761,9 @@ class ScenarioSimulator():
|
|
|
761
761
|
nodes_id = self.epanet_api.getNodeNameID()
|
|
762
762
|
nodes_elevation = self.epanet_api.getNodeElevations()
|
|
763
763
|
nodes_type = [self.epanet_api.TYPENODE[i] for i in self.epanet_api.getNodeTypeIndex()]
|
|
764
|
+
nodes_coord = [self.epanet_api.api.ENgetcoord(node_idx)
|
|
765
|
+
for node_idx in self.epanet_api.getNodeIndex()]
|
|
766
|
+
node_tank_names = self.epanet_api.getNodeTankNameID()
|
|
764
767
|
|
|
765
768
|
links_id = self.epanet_api.getLinkNameID()
|
|
766
769
|
links_data = self.epanet_api.getNodesConnectingLinksID()
|
|
@@ -773,8 +776,16 @@ class ScenarioSimulator():
|
|
|
773
776
|
|
|
774
777
|
# Build graph describing the topology
|
|
775
778
|
nodes = []
|
|
776
|
-
for
|
|
777
|
-
|
|
779
|
+
for node_id, node_elevation, node_type, node_coord in zip(nodes_id, nodes_elevation,
|
|
780
|
+
nodes_type, nodes_coord):
|
|
781
|
+
node_info = {"elevation": node_elevation,
|
|
782
|
+
"coord": node_coord,
|
|
783
|
+
"type": node_type}
|
|
784
|
+
if node_type == "TANK":
|
|
785
|
+
node_tank_idx = node_tank_names.index(node_id) + 1
|
|
786
|
+
node_info["diameter"] = float(self.epanet_api.getNodeTankDiameter(node_tank_idx))
|
|
787
|
+
|
|
788
|
+
nodes.append((node_id, node_info))
|
|
778
789
|
|
|
779
790
|
links = []
|
|
780
791
|
for link_id, link, diameter, length, roughness_coeff, bulk_coeff, wall_coeff, loss_coeff \
|
|
@@ -1739,8 +1750,7 @@ class ScenarioSimulator():
|
|
|
1739
1750
|
# Fetch data
|
|
1740
1751
|
pressure_data = self.epanet_api.getNodePressure().reshape(1, -1)
|
|
1741
1752
|
flow_data = self.epanet_api.getLinkFlows().reshape(1, -1)
|
|
1742
|
-
demand_data = self.epanet_api.getNodeActualDemand().reshape(1,
|
|
1743
|
-
-1) # TODO: Does not go back after emitter coefficient is changed back to zero
|
|
1753
|
+
demand_data = self.epanet_api.getNodeActualDemand().reshape(1, -1)
|
|
1744
1754
|
quality_node_data = self.epanet_api.getNodeActualQuality().reshape(1, -1)
|
|
1745
1755
|
quality_link_data = self.epanet_api.getLinkActualQuality().reshape(1, -1)
|
|
1746
1756
|
pumps_state_data = self.epanet_api.getLinkPumpState().reshape(1, -1)
|
|
@@ -1841,7 +1851,7 @@ class ScenarioSimulator():
|
|
|
1841
1851
|
def set_general_parameters(self, demand_model: dict = None, simulation_duration: int = None,
|
|
1842
1852
|
hydraulic_time_step: int = None, quality_time_step: int = None,
|
|
1843
1853
|
reporting_time_step: int = None, reporting_time_start: int = None,
|
|
1844
|
-
|
|
1854
|
+
flow_units_id: int = None, quality_model: dict = None) -> None:
|
|
1845
1855
|
"""
|
|
1846
1856
|
Sets some general parameters.
|
|
1847
1857
|
|
|
@@ -1886,22 +1896,22 @@ class ScenarioSimulator():
|
|
|
1886
1896
|
Start time (in seconds) at which reporting of hydraulic and quality states starts.
|
|
1887
1897
|
|
|
1888
1898
|
The default is None.
|
|
1889
|
-
|
|
1899
|
+
flow_units_id : `int`, optional
|
|
1890
1900
|
Specifies the flow units -- i.e. all flows will be reported in these units.
|
|
1891
1901
|
If None, the units from the .inp file will be used.
|
|
1892
1902
|
|
|
1893
1903
|
Must be one of the following EPANET toolkit constants:
|
|
1894
1904
|
|
|
1895
|
-
- EN_CFS
|
|
1896
|
-
- EN_GPM
|
|
1897
|
-
- EN_MGD
|
|
1898
|
-
- EN_IMGD = 3
|
|
1899
|
-
- EN_AFD
|
|
1900
|
-
- EN_LPS
|
|
1901
|
-
- EN_LPM
|
|
1902
|
-
- EN_MLD
|
|
1903
|
-
- EN_CMH
|
|
1904
|
-
- EN_CMD
|
|
1905
|
+
- EN_CFS = 0 (cubic foot/sec)
|
|
1906
|
+
- EN_GPM = 1 (gal/min)
|
|
1907
|
+
- EN_MGD = 2 (Million gal/day)
|
|
1908
|
+
- EN_IMGD = 3 (Imperial MGD)
|
|
1909
|
+
- EN_AFD = 4 (ac-foot/day)
|
|
1910
|
+
- EN_LPS = 5 (liter/sec)
|
|
1911
|
+
- EN_LPM = 6 (liter/min)
|
|
1912
|
+
- EN_MLD = 7 (Megaliter/day)
|
|
1913
|
+
- EN_CMH = 8 (cubic meter/hr)
|
|
1914
|
+
- EN_CMD = 9 (cubic meter/day)
|
|
1905
1915
|
|
|
1906
1916
|
The default is None.
|
|
1907
1917
|
quality_model : `dict`, optional
|
|
@@ -1922,8 +1932,7 @@ class ScenarioSimulator():
|
|
|
1922
1932
|
if not isinstance(simulation_duration, int) or simulation_duration <= 0:
|
|
1923
1933
|
raise ValueError("'simulation_duration' must be a positive integer specifying " +
|
|
1924
1934
|
"the number of seconds to simulate")
|
|
1925
|
-
self.epanet_api.setTimeSimulationDuration(simulation_duration)
|
|
1926
|
-
# duration from .inp file seems to break EPANET-MSX
|
|
1935
|
+
self.epanet_api.setTimeSimulationDuration(simulation_duration)
|
|
1927
1936
|
|
|
1928
1937
|
if hydraulic_time_step is not None:
|
|
1929
1938
|
if not isinstance(hydraulic_time_step, int) or hydraulic_time_step <= 0:
|
|
@@ -1958,29 +1967,29 @@ class ScenarioSimulator():
|
|
|
1958
1967
|
"greater than the hydraulic time step")
|
|
1959
1968
|
self.epanet_api.setTimeQualityStep(quality_time_step)
|
|
1960
1969
|
|
|
1961
|
-
if
|
|
1962
|
-
if
|
|
1970
|
+
if flow_units_id is not None:
|
|
1971
|
+
if flow_units_id == ToolkitConstants.EN_CFS:
|
|
1963
1972
|
self.epanet_api.setFlowUnitsCFS()
|
|
1964
|
-
elif
|
|
1973
|
+
elif flow_units_id == ToolkitConstants.EN_GPM:
|
|
1965
1974
|
self.epanet_api.setFlowUnitsGPM()
|
|
1966
|
-
elif
|
|
1975
|
+
elif flow_units_id == ToolkitConstants.EN_MGD:
|
|
1967
1976
|
self.epanet_api.setFlowUnitsMGD()
|
|
1968
|
-
elif
|
|
1977
|
+
elif flow_units_id == ToolkitConstants.EN_IMGD:
|
|
1969
1978
|
self.epanet_api.setFlowUnitsIMGD()
|
|
1970
|
-
elif
|
|
1979
|
+
elif flow_units_id == ToolkitConstants.EN_AFD:
|
|
1971
1980
|
self.epanet_api.setFlowUnitsAFD()
|
|
1972
|
-
elif
|
|
1981
|
+
elif flow_units_id == ToolkitConstants.EN_LPS:
|
|
1973
1982
|
self.epanet_api.setFlowUnitsLPS()
|
|
1974
|
-
elif
|
|
1983
|
+
elif flow_units_id == ToolkitConstants.EN_LPM:
|
|
1975
1984
|
self.epanet_api.setFlowUnitsLPM()
|
|
1976
|
-
elif
|
|
1985
|
+
elif flow_units_id == ToolkitConstants.EN_MLD:
|
|
1977
1986
|
self.epanet_api.setFlowUnitsMLD()
|
|
1978
|
-
elif
|
|
1987
|
+
elif flow_units_id == ToolkitConstants.EN_CMH:
|
|
1979
1988
|
self.epanet_api.setFlowUnitsCMH()
|
|
1980
|
-
elif
|
|
1989
|
+
elif flow_units_id == ToolkitConstants.EN_CMD:
|
|
1981
1990
|
self.epanet_api.setFlowUnitsCMD()
|
|
1982
1991
|
else:
|
|
1983
|
-
raise ValueError(f"Unknown flow units '{
|
|
1992
|
+
raise ValueError(f"Unknown flow units '{flow_units_id}'")
|
|
1984
1993
|
|
|
1985
1994
|
if quality_model is not None:
|
|
1986
1995
|
if quality_model["type"] == "NONE":
|
|
@@ -1989,7 +1998,7 @@ class ScenarioSimulator():
|
|
|
1989
1998
|
self.epanet_api.setQualityType("age")
|
|
1990
1999
|
elif quality_model["type"] == "CHEM":
|
|
1991
2000
|
self.epanet_api.setQualityType("chem", quality_model["chemical_name"],
|
|
1992
|
-
|
|
2001
|
+
qualityunit_to_str(quality_model["units"]))
|
|
1993
2002
|
elif quality_model["type"] == "TRACE":
|
|
1994
2003
|
self.epanet_api.setQualityType("trace", quality_model["trace_node_id"])
|
|
1995
2004
|
else:
|