From f9709fbcaff3450da2a11bb3c67b776d6ca9c50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Artelt?= Date: Sat, 1 Jun 2024 14:33:42 +0200 Subject: [PATCH] Store measurement units in NetworkTopology --- epyt_flow/simulation/scenario_simulator.py | 26 ++++++++++- epyt_flow/topology.py | 53 +++++++++++++++++++--- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/epyt_flow/simulation/scenario_simulator.py b/epyt_flow/simulation/scenario_simulator.py index e9b317c..c4d119f 100644 --- a/epyt_flow/simulation/scenario_simulator.py +++ b/epyt_flow/simulation/scenario_simulator.py @@ -27,7 +27,7 @@ from .events import SystemEvent, Leakage, ActuatorEvent, SensorFault, SensorReadingAttack, \ SensorReadingEvent from .scada import ScadaData, AdvancedControlModule -from ..topology import NetworkTopology +from ..topology import NetworkTopology, UNITS_SIMETRIC, UNITS_USCUSTOM from ..utils import get_temp_folder @@ -604,6 +604,27 @@ def get_flow_units(self) -> int: """ return self.epanet_api.api.ENgetflowunits() + def get_units_category(self) -> int: + """ + Gets the category of units -- i.e. US Customary or SI Metric units. + + Will be one of the following constants: + + - UNITS_USCUSTOM = 0 (US Customary) + - UNITS_SIMETRIC = 1 (SI Metric) + + Returns + ------- + `int` + Units category. + """ + if self.get_flow_units() in [ToolkitConstants.EN_CFS, ToolkitConstants.EN_GPM, + ToolkitConstants.EN_MGD, ToolkitConstants.EN_IMGD, + ToolkitConstants.EN_AFD]: + return UNITS_USCUSTOM + else: + return UNITS_SIMETRIC + def get_hydraulic_time_step(self) -> int: """ Gets the hydraulic time step -- i.e. time step in the hydraulic simulation. @@ -764,7 +785,8 @@ def get_topology(self) -> NetworkTopology: "bulk_coeff": bulk_coeff, "wall_coeff": wall_coeff, "loss_coeff": loss_coeff})) - return NetworkTopology(f_inp=self.f_inp_in, nodes=nodes, links=links) + return NetworkTopology(f_inp=self.f_inp_in, nodes=nodes, links=links, + units=self.get_units_category()) def randomize_demands(self) -> None: """ diff --git a/epyt_flow/topology.py b/epyt_flow/topology.py index 41487fc..5b1c264 100644 --- a/epyt_flow/topology.py +++ b/epyt_flow/topology.py @@ -1,6 +1,8 @@ """ Module provides a class for representing the topology of WDN. """ +from copy import deepcopy +import warnings import numpy as np import networkx as nx from scipy.sparse import bsr_array @@ -8,6 +10,10 @@ from .serialization import serializable, JsonSerializable, NETWORK_TOPOLOGY_ID +UNITS_USCUSTOM = 0 +UNITS_SIMETRIC = 1 + + @serializable(NETWORK_TOPOLOGY_ID, ".epytflow_topology") class NetworkTopology(nx.Graph, JsonSerializable): """ @@ -22,13 +28,28 @@ class NetworkTopology(nx.Graph, JsonSerializable): links : `list[tuple[tuple[str, str], dict]]` List of all links/pipes -- i.e. link ID, ID of connecting nodes, and link information such as pipe diameter, length, etc. + units : `int` + Measurement units category. + + Must be one of the following constants: + + - UNITS_USCUSTOM = 0 (US Customary) + - UNITS_SIMETRIC = 1 (SI Metric) """ def __init__(self, f_inp: str, nodes: list[tuple[str, dict]], - links: list[tuple[str, tuple[str, str], dict]], **kwds): + links: list[tuple[str, tuple[str, str], dict]], + units: int = None, + **kwds): super().__init__(name=f_inp, **kwds) self.__nodes = nodes self.__links = links + self.__units = units + + if units is None: + warnings.warn("Loading a file that was created with an outdated version of EPyT-Flow" + + " -- support of such old files will be removed in the next release!", + DeprecationWarning) for node_id, node_info in nodes: node_elevation = node_info["elevation"] @@ -104,23 +125,43 @@ def get_link_info(self, link_id) -> dict: raise ValueError(f"Unknown link '{link_id}'") + @property + def units(self) -> int: + """ + Gets the used measurement units category. + + Will be one of the following constants: + + - UNITS_USCUSTOM = 0 (US Customary) + - UNITS_SIMETRIC = 1 (SI Metric) + + Returns + ------- + `int` + Measurement units category. + """ + return self.__units + def __eq__(self, other) -> bool: if not isinstance(other, NetworkTopology): raise TypeError("Can not compare 'NetworkTopology' instance to " + f"'{type(other)}' instance") return super().__eq__(other) and \ - self.get_all_nodes() == other.get_all_nodes() and \ - all(link_a[0] == link_b[0] and all(link_a[1] == link_b[1]) - for link_a, link_b in zip(self.get_all_links(), other.get_all_links())) + self.get_all_nodes() == other.get_all_nodes() \ + and all(link_a[0] == link_b[0] and all(link_a[1] == link_b[1]) + for link_a, link_b in zip(self.get_all_links(), other.get_all_links())) \ + and self.__units == other.units def __str__(self) -> str: - return f"f_inp: {self.name} nodes: {self.__nodes} links: {self.__links}" + return f"f_inp: {self.name} nodes: {self.__nodes} links: {self.__links} " +\ + f"units: {self.__units}" def get_attributes(self) -> dict: return super().get_attributes() | {"f_inp": self.name, "nodes": self.__nodes, - "links": self.__links} + "links": self.__links, + "units": self.__units} def get_adj_matrix(self) -> bsr_array: """