From 08b1dbf2649b380d19a1d38801a7f27de9a6cc43 Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Wed, 24 Apr 2024 17:02:40 +0300 Subject: [PATCH 01/12] getMSXComputedLinkQualitySpecie + getMSXComputedNodeQualitySpecie + Description --- epyt/epanet.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/epyt/epanet.py b/epyt/epanet.py index 7155e24..03cde81 100644 --- a/epyt/epanet.py +++ b/epyt/epanet.py @@ -12747,6 +12747,18 @@ def addMSXPattern(self, *args): return index def getMSXComputedQualitySpecie(self, species=None): + """ Returns the node/link quality for specific specie. + + Example : + d = epanet('net2-cl2.inp') + d.loadMSXFile('net2-cl2.msx') + MSX_comp = d.getMSXComputedQualitySpecie(['CL2']) + MSX_comp.NodeQuality row: time, col: node index + MSX_comp.LinkQuality row: time, col: link index + MSX_comp.Time + + See also getMSXComputedQualityNode, getMSXComputedQualityLink. + """ if self.getMSXSpeciesCount() == 0: return -1 if species is None: @@ -12805,7 +12817,53 @@ def getMSXComputedQualitySpecie(self, species=None): range(int(self.getTimeSimulationDuration() / msx_time_step) + 1)] return value + def getMSXComputedNodeQualitySpecie(self, node_indices, species_id): + """ Returns the node quality for specific specie. + + Example : + d = epanet('net2-cl2.inp') + d.loadMSXFile('net2-cl2.msx') + node_indices = [1,2,3] + MSX_comp = d.getMSXComputedNodeQualitySpecie(node_indices, 'CL2') + MSX_comp.NodeQuality row: time, col: node index + MSX_comp.Time + + See also getMSXComputedQualitySpecie, getMSXComputedLinkQualitySpecie.""" + merged = [] + MSX_comp = self.getMSXComputedQualitySpecie([species_id]) + MSX_comp_node = MSX_comp.NodeQuality + for i in node_indices: + column = MSX_comp_node[i] + merged.append(column) + value = EpytValues() + value.NodeQuality, value.Time = {}, {} + value.NodeQuality = merged + value.Time = MSX_comp.Time + return value + + def getMSXComputedLinkQualitySpecie(self, node_indices, species_id): + """ Returns the link quality for specific specie. + Example : + d = epanet('net2-cl2.inp') + d.loadMSXFile('net2-cl2.msx') + node_indices = [1,2,3,4] + MSX_comp = d.getMSXComputedLinkQualitySpecie(node_indices, 'CL2') + MSX_comp.LinkQuality row: time, col: node index + MSX_comp.Time + + See also getMSXComputedQualitySpecie, getMSXComputedNodeQualitySpecie.""" + merged = [] + MSX_comp = self.getMSXComputedQualitySpecie([species_id]) + MSX_comp_Link = MSX_comp.LinkQuality + for i in node_indices: + column = MSX_comp_Link[i] + merged.append(column) + value = EpytValues() + value.LinkQuality, value.Time = {}, {} + value.LinkQuality = merged + value.Time = MSX_comp.Time + return value class epanetapi: """ EPANET Toolkit functions - API From 741fcab74499fb5fde86d88b672c82f012a0bbad Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Tue, 30 Apr 2024 02:55:42 +0300 Subject: [PATCH 02/12] SetMSXLinkInitqualValue and setMSXNodeInitqualValue + updated readme --- README.md | 5 +++++ epyt/epanet.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/README.md b/README.md index c2919a4..bb8dc50 100644 --- a/README.md +++ b/README.md @@ -532,6 +532,9 @@ If you want to contribute, please check out our [Code of Conduct](https://github |unloadMSX|Closes the EPANET-MSX toolkit system| |addMSXPattern|Adds a new, empty MSX source time pattern to the project| |initializeMSXQualityAnalysis|Initializes the MSX system before solving for water quality results in step-wise fashion| +|getMSXComputedQualitySpecie|Retrieves the quality values for specific specie (e.g getMSXComputedQualitySpecie('CL2'))| +|getMSXComputedLinkQualitySpecie|Returns the link quality for specific specie| +|getMSXComputedNodeQualitySpecie|Returns the node quality for specific specie| |stepMSXQualityAnalysisTimeLeft|Advances the water quality solution through a single water quality time step when performing a step-wise simulation| |saveMSXFile|Saves the data associated with the current MSX project into a new MSX input file| |saveMSXQualityFile|Saves water quality results computed for each node, link and reporting time period to a named binary file| @@ -601,6 +604,8 @@ If you want to contribute, please check out our [Code of Conduct](https://github |setMSXParametersPipesValue|Assigns a value to a particular reaction parameter for given pipes| |setMSXParametersTanksValue|Assigns a value to a particular reaction parameter for given tanks| |setMSXConstantsValue|Assigns a new value to a specific reaction constant| +|setMSXLinkInitqualValue|Assigns an initial concentration of chemical species to links| +|setMSXNodeInitqualValue|Assigns an initial concentration of chemical species to nodes| |useMSXHydraulicFile|Uses a previously saved EPANET hydraulics file as the source of hydraulic information| diff --git a/epyt/epanet.py b/epyt/epanet.py index 03cde81..68f510d 100644 --- a/epyt/epanet.py +++ b/epyt/epanet.py @@ -12864,6 +12864,52 @@ def getMSXComputedLinkQualitySpecie(self, node_indices, species_id): value.LinkQuality = merged value.Time = MSX_comp.Time return value + + def setMSXLinkInitqualValue(self, value): + """" + Sets all links initial quality value. + + Example: + linkIndex=0 + speciesIndex=0 + values = [[0] * linkIndex for _ in range(speciesIndex)] + values=d.getMSXLinkInitqualValue() + values[linkIndex][speciesIndex]=1500 + d.setMSXLinkInitqualValue(values) + x=d.getMSXLinkInitqualValue() + + See also getMSXLinkInitqualValue, setMSXNodeInitqualValue. + """ + for i in range(len(value)): + for j in range(len(value[0])): + self.msx.MSXsetinitqual(1, i+1, j+1, value[i][j]) + + def setMSXSources(self, nodeID, speciesID, sourcetype, concentration, patID ): + MSXTYPESOURCE = {'NOSOURCE', 'CONCEN', 'MASS', 'SETPOINT', 'FLOWPACED'} + node = self.getNodeIndex(nodeID) + species = self.getMSXSpeciesIndex(speciesID) + type = (list(MSXTYPESOURCE).index(sourcetype.upper()) if sourcetype.upper() in MSXTYPESOURCE else -1) - 2 + pat = self.getMSXPatternsIndex(patID) + self.msx.MSXsetsource(node, species, type, concentration, pat) + + def setMSXNodeInitqualValue(self, value): + """ + Sets all nodes initial quality value. + + Example: + linkIndex=0 + speciesIndex=0 + values = [[0] * linkIndex for _ in range(speciesIndex)] + values=d.getMSXNodeInitqualValue() + values[linkIndex][speciesIndex]=1500 + d.setMSXNodeInitqualValue(values) + x=d.getMSXNodeInitqualValue() + See also getMSXNodeInitqualValue, setMSXLinkInitqualValue. + """ + for i in range(len(value)): + for j in range(len(value[0])): + self.msx.MSXsetinitqual(0, i+1, j+1, value[i][j]) + class epanetapi: """ EPANET Toolkit functions - API From 07965a581dcf734f231b94cfd8502b1b5ddcc5a4 Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Tue, 30 Apr 2024 05:28:22 +0300 Subject: [PATCH 03/12] fixed getMSXPatternsIndex when input = 1 item + setMSXSource --- epyt/epanet.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/epyt/epanet.py b/epyt/epanet.py index 68f510d..e0b9e43 100644 --- a/epyt/epanet.py +++ b/epyt/epanet.py @@ -11774,16 +11774,22 @@ def getMSXPatternsIndex(self, varagin=None): setMSXPattern, setMSXPatternMatrix, setMSXPatternValue.""" x = self.getMSXSpeciesCount() value = {} + flag = 0 if varagin is None: varagin = {} varagin = self.getMSXPatternsNameID() y = varagin else: + if isinstance(varagin, str): + flag = 1 y = varagin MSX_PATTERN = self.ToolkitConstants.MSX_PATTERN if x > 0: - for i in y: - value[i] = self.msx.MSXgetindex(MSX_PATTERN, i) + if flag == 1: + value[0] = self.msx.MSXgetindex(MSX_PATTERN, y) + else: + for i in y: + value[i] = self.msx.MSXgetindex(MSX_PATTERN, i) output = list(value.values()) return output @@ -12888,8 +12894,20 @@ def setMSXSources(self, nodeID, speciesID, sourcetype, concentration, patID ): MSXTYPESOURCE = {'NOSOURCE', 'CONCEN', 'MASS', 'SETPOINT', 'FLOWPACED'} node = self.getNodeIndex(nodeID) species = self.getMSXSpeciesIndex(speciesID) - type = (list(MSXTYPESOURCE).index(sourcetype.upper()) if sourcetype.upper() in MSXTYPESOURCE else -1) - 2 + species=species[0] pat = self.getMSXPatternsIndex(patID) + pat = pat[0] + if sourcetype == 'NOSOURCE' or sourcetype == 'nosource': + type = -1 + elif sourcetype == 'CONCEN' or sourcetype == 'concern': + type = 0 + elif sourcetype == 'MASS' or sourcetype == 'mass': + type = 1 + elif sourcetype == 'SETPOINT' or sourcetype == 'setpoint': + type = 2 + elif sourcetype == 'FLOWPACED' or sourcetype == 'flowpaced': + type = 3 + self.msx.MSXsetsource(node, species, type, concentration, pat) def setMSXNodeInitqualValue(self, value): @@ -16363,6 +16381,7 @@ def MSXsetsource(self, node, species, type, level, pat): pat: the index of the time pattern used to add variability to the source's baseline level ( use 0 if the source has a constant strength) """ level = c_double(level) + pat = c_int(pat) type = c_int(type) err = self.msx_lib.MSXsetsource(node, species, type, level, pat) From 6f895ddf47963c98c199d81f900a6ffb4b8d5189 Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Tue, 30 Apr 2024 05:33:40 +0300 Subject: [PATCH 04/12] Revert "fixed getMSXPatternsIndex when input = 1 item + setMSXSource" This reverts commit 07965a581dcf734f231b94cfd8502b1b5ddcc5a4. --- epyt/epanet.py | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/epyt/epanet.py b/epyt/epanet.py index e0b9e43..68f510d 100644 --- a/epyt/epanet.py +++ b/epyt/epanet.py @@ -11774,22 +11774,16 @@ def getMSXPatternsIndex(self, varagin=None): setMSXPattern, setMSXPatternMatrix, setMSXPatternValue.""" x = self.getMSXSpeciesCount() value = {} - flag = 0 if varagin is None: varagin = {} varagin = self.getMSXPatternsNameID() y = varagin else: - if isinstance(varagin, str): - flag = 1 y = varagin MSX_PATTERN = self.ToolkitConstants.MSX_PATTERN if x > 0: - if flag == 1: - value[0] = self.msx.MSXgetindex(MSX_PATTERN, y) - else: - for i in y: - value[i] = self.msx.MSXgetindex(MSX_PATTERN, i) + for i in y: + value[i] = self.msx.MSXgetindex(MSX_PATTERN, i) output = list(value.values()) return output @@ -12894,20 +12888,8 @@ def setMSXSources(self, nodeID, speciesID, sourcetype, concentration, patID ): MSXTYPESOURCE = {'NOSOURCE', 'CONCEN', 'MASS', 'SETPOINT', 'FLOWPACED'} node = self.getNodeIndex(nodeID) species = self.getMSXSpeciesIndex(speciesID) - species=species[0] + type = (list(MSXTYPESOURCE).index(sourcetype.upper()) if sourcetype.upper() in MSXTYPESOURCE else -1) - 2 pat = self.getMSXPatternsIndex(patID) - pat = pat[0] - if sourcetype == 'NOSOURCE' or sourcetype == 'nosource': - type = -1 - elif sourcetype == 'CONCEN' or sourcetype == 'concern': - type = 0 - elif sourcetype == 'MASS' or sourcetype == 'mass': - type = 1 - elif sourcetype == 'SETPOINT' or sourcetype == 'setpoint': - type = 2 - elif sourcetype == 'FLOWPACED' or sourcetype == 'flowpaced': - type = 3 - self.msx.MSXsetsource(node, species, type, concentration, pat) def setMSXNodeInitqualValue(self, value): @@ -16381,7 +16363,6 @@ def MSXsetsource(self, node, species, type, level, pat): pat: the index of the time pattern used to add variability to the source's baseline level ( use 0 if the source has a constant strength) """ level = c_double(level) - pat = c_int(pat) type = c_int(type) err = self.msx_lib.MSXsetsource(node, species, type, level, pat) From 86c5e6e1df07afb691a4d79f37180625f7d60852 Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Tue, 30 Apr 2024 05:43:49 +0300 Subject: [PATCH 05/12] Reapply "fixed getMSXPatternsIndex when input = 1 item + setMSXSource" This reverts commit 6f895ddf47963c98c199d81f900a6ffb4b8d5189. --- epyt/epanet.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/epyt/epanet.py b/epyt/epanet.py index 68f510d..e0b9e43 100644 --- a/epyt/epanet.py +++ b/epyt/epanet.py @@ -11774,16 +11774,22 @@ def getMSXPatternsIndex(self, varagin=None): setMSXPattern, setMSXPatternMatrix, setMSXPatternValue.""" x = self.getMSXSpeciesCount() value = {} + flag = 0 if varagin is None: varagin = {} varagin = self.getMSXPatternsNameID() y = varagin else: + if isinstance(varagin, str): + flag = 1 y = varagin MSX_PATTERN = self.ToolkitConstants.MSX_PATTERN if x > 0: - for i in y: - value[i] = self.msx.MSXgetindex(MSX_PATTERN, i) + if flag == 1: + value[0] = self.msx.MSXgetindex(MSX_PATTERN, y) + else: + for i in y: + value[i] = self.msx.MSXgetindex(MSX_PATTERN, i) output = list(value.values()) return output @@ -12888,8 +12894,20 @@ def setMSXSources(self, nodeID, speciesID, sourcetype, concentration, patID ): MSXTYPESOURCE = {'NOSOURCE', 'CONCEN', 'MASS', 'SETPOINT', 'FLOWPACED'} node = self.getNodeIndex(nodeID) species = self.getMSXSpeciesIndex(speciesID) - type = (list(MSXTYPESOURCE).index(sourcetype.upper()) if sourcetype.upper() in MSXTYPESOURCE else -1) - 2 + species=species[0] pat = self.getMSXPatternsIndex(patID) + pat = pat[0] + if sourcetype == 'NOSOURCE' or sourcetype == 'nosource': + type = -1 + elif sourcetype == 'CONCEN' or sourcetype == 'concern': + type = 0 + elif sourcetype == 'MASS' or sourcetype == 'mass': + type = 1 + elif sourcetype == 'SETPOINT' or sourcetype == 'setpoint': + type = 2 + elif sourcetype == 'FLOWPACED' or sourcetype == 'flowpaced': + type = 3 + self.msx.MSXsetsource(node, species, type, concentration, pat) def setMSXNodeInitqualValue(self, value): @@ -16363,6 +16381,7 @@ def MSXsetsource(self, node, species, type, level, pat): pat: the index of the time pattern used to add variability to the source's baseline level ( use 0 if the source has a constant strength) """ level = c_double(level) + pat = c_int(pat) type = c_int(type) err = self.msx_lib.MSXsetsource(node, species, type, level, pat) From a2df9b105ac5456c85730179cac0d9c5ca84b79e Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Tue, 30 Apr 2024 05:45:00 +0300 Subject: [PATCH 06/12] removed msx=True --- epyt/tests/testMSXunit.py | 293 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 epyt/tests/testMSXunit.py diff --git a/epyt/tests/testMSXunit.py b/epyt/tests/testMSXunit.py new file mode 100644 index 0000000..5441b39 --- /dev/null +++ b/epyt/tests/testMSXunit.py @@ -0,0 +1,293 @@ +from epyt.epanet import epanet, epanetmsxapi +from epyt import networks +import numpy as np +import unittest +import os + + +class MSXtest(unittest.TestCase): + + def setUp(self): + """Call before every test case.""" + # Create EPANET object using the INP file + dirname = os.path.dirname(networks.__file__) + inpname = os.path.join(dirname, 'msx-examples', 'Net3-NH2CL.inp') + file_path = os.path.join(dirname, 'msx-examples', 'Net3-NH2CL.msx') + + self.epanetClass = epanet(inpname) + + self.msxClass = epanetmsxapi(file_path) + + def tearDown(self): + """Call after every test case.""" + self.msxClass.MSXclose() + self.epanetClass.unload() + + """ ------------------------------------------------------------------------- """ + + def test_MSXgetsource(self): + self.assertEqual(self.msxClass.MSXgetsource(1, 14), + ('SETPOINT', 2.0, 0), 'Wrong source comment output') + self.assertEqual(self.msxClass.MSXgetsource(2, 1), + ('CONCEN', 0.8, 0), 'Wrong source comment output') + self.assertEqual(self.msxClass.MSXgetsource(3, 2), + ('MASS', 0.5, 0), 'Wrong source comment output') + self.assertEqual(self.msxClass.MSXgetsource(4, 3), + ('FLOWPACED', 4.5, 0), 'Wrong source comment output') + + def test_MSXsetsource(self): + self.msxClass.MSXsetsource(1, 1, -1, 10.565, 1) + self.assertEqual(self.msxClass.MSXgetsource(1, 1), + ('NOSOURCE', 10.565, 1), 'Wrong source comment output') + self.msxClass.MSXsetsource(1, 1, 0, 10.565, 1) + self.assertEqual(self.msxClass.MSXgetsource(1, 1), + ('CONCEN', 10.565, 1), 'Wrong source comment output') + self.msxClass.MSXsetsource(1, 1, 1, 10.565, 1) + self.assertEqual(self.msxClass.MSXgetsource(1, 1), + ('MASS', 10.565, 1), 'Wrong source comment output') + self.msxClass.MSXsetsource(1, 1, 2, 10.565, 1) + self.assertEqual(self.msxClass.MSXgetsource(1, 1), + ('SETPOINT', 10.565, 1), 'Wrong source comment output') + self.msxClass.MSXsetsource(1, 1, 3, 10.565, 1) + self.assertEqual(self.msxClass.MSXgetsource(1, 1), + ('FLOWPACED', 10.565, 1), 'Wrong source comment output') + # set an integer value for level test_MSXsetsource + self.msxClass.MSXsetsource(1, 1, 3, 10, 1) + self.assertEqual(self.msxClass.MSXgetsource(1, 1), + ('FLOWPACED', 10, 1), 'Wrong source comment output') + def test_MSXgetspecies(self): + self.assertEqual(self.msxClass.MSXgetspecies(1), ('BULK', 'MMOL', 1.0e-8, 0.0001), + 'Wrong species comment output') + self.assertEqual(self.msxClass.MSXgetspecies(2), ('BULK', 'MMOL', 1.0e-8, 0.0001), + 'Wrong species comment output') + self.assertEqual(self.msxClass.MSXgetspecies(3), ('BULK', 'MMOL', 1.0e-8, 0.0001), + 'Wrong species comment output') + self.assertEqual(self.msxClass.MSXgetspecies(4), ('BULK', 'MMOL', 1.0e-8, 0.0001), + 'Wrong species comment output') + self.assertEqual(self.msxClass.MSXgetspecies(5), ('BULK', 'MMOL', 1.0e-8, 0.0001), + 'Wrong species comment output') + + + def test_MSXgetconstant(self): + + self.assertEqual(self.msxClass.MSXgetconstant(1), 0.02, + 'Wrong constant comment output') + self.assertEqual(self.msxClass.MSXgetconstant(2), 0.50, + 'Wrong constant comment output') + + + def test_MSXsetconstant(self): + + # set an integer value + self.msxClass.MSXsetconstant(1, 69) + self.assertEqual(self.msxClass.MSXgetconstant(1), 69, + 'Wrong set/get constant comment output') + # set a float value + self.msxClass.MSXsetconstant(1, 69.420) + self.assertEqual(self.msxClass.MSXgetconstant(1), 69.420, + 'Wrong set/get constant comment output') + + def testMSXgetinitqual(self): + self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 9), 2.818e-08, + 'Wrong get init qual comment output') + self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 10), 3.55e-7, + 'Wrong get init qual comment output') + self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 8), 0.004, + 'Wrong get init qual comment output') + self.assertEqual(self.msxClass.MSXgetinitqual(0, 1, 9), 2.818e-08, + 'Wrong get init qual comment output') + self.assertEqual(self.msxClass.MSXgetinitqual(0, 1, 10), 3.55e-7, + 'Wrong get init qual comment output') + self.assertEqual(self.msxClass.MSXgetinitqual(0, 1, 8), 0.004, + 'Wrong get init qual comment output') + + def testMSXsetinitqual(self): + # set value as integer testMSXsetinitqual + self.msxClass.MSXsetinitqual(1, 1, 1, 69) + self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 1), 69, + 'Wrong set/get init qual comment output') + # set value as float testMSXsetinitqual + self.msxClass.MSXsetinitqual(1, 1, 1, 69.420) + self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 1), 69.420, + 'Wrong set/get init qual comment output') + + def test_MSXsetinitqual(self): + #set value as integer test_MSXsetinitqual + self.msxClass.MSXsetinitqual(1,1,1,69) + self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 1), 69, + 'Wrong set/get init qual comment output') + #set value as float test_MSXsetinitqual + self.msxClass.MSXsetinitqual(1, 1, 1, 69.420) + self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 1), 69.420, + 'Wrong set/get init qual comment output') + + def test_MSXsetpatternvalue(self): + + #set value as integer test_MSXsetpatternvalue + self.msxClass.MSXsetpatternvalue(1,1,69) + self.assertEqual(self.msxClass.MSXgetpatternvalue(1, 1), 69, + 'Wrong set/get patternvalue comment output') + #set value as float test_MSXsetpatternvalue + self.msxClass.MSXsetpatternvalue(1, 1, 69.420) + self.assertEqual(self.msxClass.MSXgetpatternvalue(1, 1), 69.420, + 'Wrong set/get init patternvalue comment output') + + + def test_MSXgetIDlen(self): + + self.assertEqual(self.msxClass.MSXgetIDlen(3, 1), 4, + 'Wrong get ID len comment output') + self.assertEqual(self.msxClass.MSXgetIDlen(3, 2), 3, + 'Wrong get ID len comment output') + self.assertEqual(self.msxClass.MSXgetIDlen(3, 3), 5, + 'Wrong get ID len comment output') + + def test_MSXgetID(self): + + self.assertEqual(self.msxClass.MSXgetID(3, 1,4), 'HOCL', + 'Wrong get ID comment output') + self.assertEqual(self.msxClass.MSXgetID(3, 2,3), 'NH3', + 'Wrong get ID comment output') + self.assertEqual(self.msxClass.MSXgetID(3, 3,5), 'NH2CL', + 'Wrong get ID comment output') + + + def test_MSXgeterror(self): + + self.assertEqual(self.msxClass.MSXgeterror(516), 'Error 516 - reference made to an illegal object index.', + 'Wrong error comment output') + self.assertEqual(self.msxClass.MSXgeterror(505), 'Error 505 - could not read hydraulic results file.', + 'Wrong error comment output') + self.assertEqual(self.msxClass.MSXgeterror(503), 'Error 503 - could not open MSX input file.', + 'Wrong error comment output') + + + def test_MSXgetparameter(self): + self.assertEqual(self.msxClass.MSXgetparameter(1,1,2), 0.076, + 'Wrong error comment output') + self.assertEqual(self.msxClass.MSXgetparameter(1, 1,4), 2.3e-3, + 'Wrong error comment output') + + def test_MSXsetparameter(self): + #set value as integer test_MSXsetparameter + self.msxClass.MSXsetparameter(1,1,1,69) + self.assertEqual(self.msxClass.MSXgetparameter(1, 1, 1), 69, + 'Wrong error comment output') + #set value as float test_MSXsetparameter + self.msxClass.MSXsetparameter(1, 1, 1, 69.420) + self.assertEqual(self.msxClass.MSXgetparameter(1, 1, 1), 69.420, + 'Wrong error comment output') + + def test_MSXgetcount(self): + #for species + self.assertEqual(self.msxClass.MSXgetcount(3), 16, + 'Wrong error get count output') + #for parameters + self.assertEqual(self.msxClass.MSXgetcount(5), 11, + 'Wrong error get count output') + #for constants + self.assertEqual(self.msxClass.MSXgetcount(6), 2, + 'Wrong error get count output') + #for patterns + self.assertEqual(self.msxClass.MSXgetcount(7), 2, + 'Wrong error get count output') + + def test_MSXgetindex(self): + #testing 4 species (number 3) first , last, 1 char & more than 1 char and middle + self.assertEqual(self.msxClass.MSXgetindex(3,"HOCL"), 1, + 'Wrong error get count output') + self.assertEqual(self.msxClass.MSXgetindex(3,"cNH2CL"), 16, + 'Wrong error get count output') + self.assertEqual(self.msxClass.MSXgetindex(3,"H"), 9, + 'Wrong error get count output') + self.assertEqual(self.msxClass.MSXgetindex(3,"OH"), 10, + 'Wrong error get count output') + #testing parameters (number 5) first , last and one middle case + self.assertEqual(self.msxClass.MSXgetindex(5, "k1"), 1, + 'Wrong error get count output') + self.assertEqual(self.msxClass.MSXgetindex(5, "kDOC2"), 11, + 'Wrong error get count output') + self.assertEqual(self.msxClass.MSXgetindex(5, "k6"), 5, + 'Wrong error get count output') + #testing constants (number 6) + self.assertEqual(self.msxClass.MSXgetindex(6, "S1"), 1, + 'Wrong error get count output') + self.assertEqual(self.msxClass.MSXgetindex(6, "S2"), 2, + 'Wrong error get count output') + #testing paterns (number 7) + self.assertEqual(self.msxClass.MSXgetindex(7, "PAT1"), 1, + 'Wrong error get count output') + self.assertEqual(self.msxClass.MSXgetindex(7, "PAT2"), 2, + 'Wrong error get count output') + + def test_MSXaddpattern(self): + + y=self.msxClass.MSXgetcount(7) + self.msxClass.MSXaddpattern("Johnnys") + self.assertEqual(self.msxClass.MSXgetcount(7), y+1, + 'Wrong error add patter output') + + def test_MSXsetpatter(self): + self.msxClass.MSXaddpattern("JohnLegend") + x = self.msxClass.MSXgetindex(7, "JohnLegend") + mult = [0.5, 0.8, 1.2, 1.0, 0.7, 0.3] + self.msxClass.MSXsetpattern(x, mult, 6) + + self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 1), 0.5, + 'Wrong set/get patternvalue comment output') + self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 2), 0.8, + 'Wrong set/get patternvalue comment output') + self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 3), 1.2, + 'Wrong set/get patternvalue comment output') + self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 4), 1.0, + 'Wrong set/get patternvalue comment output') + self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 5), 0.7, + 'Wrong set/get patternvalue comment output') + self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 6), 0.3, + 'Wrong set/get patternvalue comment output') + + def test_MSXsavesmsxfile(self): + filename = "JohntheLegend.msx" + self.msxClass.MSXsavemsxfile(filename) + full_path = os.path.join(os.getcwd(), filename) + if os.path.exists(full_path): + print(f"The file {filename} exists in the current directory.") + else: + print(f"The file {filename} does not exist in the current directory.") + + + def test_MSXgetqual(self): + + #self.msxClass.MSXclose() + #self.epanetClass.unload() + inpname = os.path.join(os.getcwd(), 'epyt', 'networks', 'msx-examples', 'net2-cl2.inp') + self.epanetClass = epanet(inpname) + file_path = os.path.join(os.getcwd(), 'epyt', 'networks', 'msx-examples', 'net2-cl2.msx') + self.msxClass = epanetmsxapi(file_path) + + self.msxClass.MSXsolveH() + self.msxClass.MSXsolveQ() + t = 0 + tleft = 0 + self.msxClass.MSXinit(0) + c = 0 + while True: + t, tleft = self.msxClass.MSXstep() + c = c + 1 + if c == 1: + self.assertEqual(self.msxClass.MSXgetqual(0, 1,1), 0.8000000188349043, + 'Wrong get qual comment output') + if c == 85: + self.assertEqual(self.msxClass.MSXgetqual(0,1,1), 0.7991662288393907, + 'Wrong get qual comment output') + if c == 660: + self.assertEqual(self.msxClass.MSXgetqual(0,1,1), 0.7999999830262526, + 'Wrong get qual comment output') + if tleft <= 0: + break + + + + +if __name__ == "__main__": + unittest.main() # run all tests From b85db0b8e906bcca8d6f14d7b3e7d137c275e141 Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Tue, 30 Apr 2024 05:53:48 +0300 Subject: [PATCH 07/12] Revert "removed msx=True" This reverts commit a2df9b105ac5456c85730179cac0d9c5ca84b79e. --- epyt/tests/testMSXunit.py | 293 -------------------------------------- 1 file changed, 293 deletions(-) delete mode 100644 epyt/tests/testMSXunit.py diff --git a/epyt/tests/testMSXunit.py b/epyt/tests/testMSXunit.py deleted file mode 100644 index 5441b39..0000000 --- a/epyt/tests/testMSXunit.py +++ /dev/null @@ -1,293 +0,0 @@ -from epyt.epanet import epanet, epanetmsxapi -from epyt import networks -import numpy as np -import unittest -import os - - -class MSXtest(unittest.TestCase): - - def setUp(self): - """Call before every test case.""" - # Create EPANET object using the INP file - dirname = os.path.dirname(networks.__file__) - inpname = os.path.join(dirname, 'msx-examples', 'Net3-NH2CL.inp') - file_path = os.path.join(dirname, 'msx-examples', 'Net3-NH2CL.msx') - - self.epanetClass = epanet(inpname) - - self.msxClass = epanetmsxapi(file_path) - - def tearDown(self): - """Call after every test case.""" - self.msxClass.MSXclose() - self.epanetClass.unload() - - """ ------------------------------------------------------------------------- """ - - def test_MSXgetsource(self): - self.assertEqual(self.msxClass.MSXgetsource(1, 14), - ('SETPOINT', 2.0, 0), 'Wrong source comment output') - self.assertEqual(self.msxClass.MSXgetsource(2, 1), - ('CONCEN', 0.8, 0), 'Wrong source comment output') - self.assertEqual(self.msxClass.MSXgetsource(3, 2), - ('MASS', 0.5, 0), 'Wrong source comment output') - self.assertEqual(self.msxClass.MSXgetsource(4, 3), - ('FLOWPACED', 4.5, 0), 'Wrong source comment output') - - def test_MSXsetsource(self): - self.msxClass.MSXsetsource(1, 1, -1, 10.565, 1) - self.assertEqual(self.msxClass.MSXgetsource(1, 1), - ('NOSOURCE', 10.565, 1), 'Wrong source comment output') - self.msxClass.MSXsetsource(1, 1, 0, 10.565, 1) - self.assertEqual(self.msxClass.MSXgetsource(1, 1), - ('CONCEN', 10.565, 1), 'Wrong source comment output') - self.msxClass.MSXsetsource(1, 1, 1, 10.565, 1) - self.assertEqual(self.msxClass.MSXgetsource(1, 1), - ('MASS', 10.565, 1), 'Wrong source comment output') - self.msxClass.MSXsetsource(1, 1, 2, 10.565, 1) - self.assertEqual(self.msxClass.MSXgetsource(1, 1), - ('SETPOINT', 10.565, 1), 'Wrong source comment output') - self.msxClass.MSXsetsource(1, 1, 3, 10.565, 1) - self.assertEqual(self.msxClass.MSXgetsource(1, 1), - ('FLOWPACED', 10.565, 1), 'Wrong source comment output') - # set an integer value for level test_MSXsetsource - self.msxClass.MSXsetsource(1, 1, 3, 10, 1) - self.assertEqual(self.msxClass.MSXgetsource(1, 1), - ('FLOWPACED', 10, 1), 'Wrong source comment output') - def test_MSXgetspecies(self): - self.assertEqual(self.msxClass.MSXgetspecies(1), ('BULK', 'MMOL', 1.0e-8, 0.0001), - 'Wrong species comment output') - self.assertEqual(self.msxClass.MSXgetspecies(2), ('BULK', 'MMOL', 1.0e-8, 0.0001), - 'Wrong species comment output') - self.assertEqual(self.msxClass.MSXgetspecies(3), ('BULK', 'MMOL', 1.0e-8, 0.0001), - 'Wrong species comment output') - self.assertEqual(self.msxClass.MSXgetspecies(4), ('BULK', 'MMOL', 1.0e-8, 0.0001), - 'Wrong species comment output') - self.assertEqual(self.msxClass.MSXgetspecies(5), ('BULK', 'MMOL', 1.0e-8, 0.0001), - 'Wrong species comment output') - - - def test_MSXgetconstant(self): - - self.assertEqual(self.msxClass.MSXgetconstant(1), 0.02, - 'Wrong constant comment output') - self.assertEqual(self.msxClass.MSXgetconstant(2), 0.50, - 'Wrong constant comment output') - - - def test_MSXsetconstant(self): - - # set an integer value - self.msxClass.MSXsetconstant(1, 69) - self.assertEqual(self.msxClass.MSXgetconstant(1), 69, - 'Wrong set/get constant comment output') - # set a float value - self.msxClass.MSXsetconstant(1, 69.420) - self.assertEqual(self.msxClass.MSXgetconstant(1), 69.420, - 'Wrong set/get constant comment output') - - def testMSXgetinitqual(self): - self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 9), 2.818e-08, - 'Wrong get init qual comment output') - self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 10), 3.55e-7, - 'Wrong get init qual comment output') - self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 8), 0.004, - 'Wrong get init qual comment output') - self.assertEqual(self.msxClass.MSXgetinitqual(0, 1, 9), 2.818e-08, - 'Wrong get init qual comment output') - self.assertEqual(self.msxClass.MSXgetinitqual(0, 1, 10), 3.55e-7, - 'Wrong get init qual comment output') - self.assertEqual(self.msxClass.MSXgetinitqual(0, 1, 8), 0.004, - 'Wrong get init qual comment output') - - def testMSXsetinitqual(self): - # set value as integer testMSXsetinitqual - self.msxClass.MSXsetinitqual(1, 1, 1, 69) - self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 1), 69, - 'Wrong set/get init qual comment output') - # set value as float testMSXsetinitqual - self.msxClass.MSXsetinitqual(1, 1, 1, 69.420) - self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 1), 69.420, - 'Wrong set/get init qual comment output') - - def test_MSXsetinitqual(self): - #set value as integer test_MSXsetinitqual - self.msxClass.MSXsetinitqual(1,1,1,69) - self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 1), 69, - 'Wrong set/get init qual comment output') - #set value as float test_MSXsetinitqual - self.msxClass.MSXsetinitqual(1, 1, 1, 69.420) - self.assertEqual(self.msxClass.MSXgetinitqual(1, 1, 1), 69.420, - 'Wrong set/get init qual comment output') - - def test_MSXsetpatternvalue(self): - - #set value as integer test_MSXsetpatternvalue - self.msxClass.MSXsetpatternvalue(1,1,69) - self.assertEqual(self.msxClass.MSXgetpatternvalue(1, 1), 69, - 'Wrong set/get patternvalue comment output') - #set value as float test_MSXsetpatternvalue - self.msxClass.MSXsetpatternvalue(1, 1, 69.420) - self.assertEqual(self.msxClass.MSXgetpatternvalue(1, 1), 69.420, - 'Wrong set/get init patternvalue comment output') - - - def test_MSXgetIDlen(self): - - self.assertEqual(self.msxClass.MSXgetIDlen(3, 1), 4, - 'Wrong get ID len comment output') - self.assertEqual(self.msxClass.MSXgetIDlen(3, 2), 3, - 'Wrong get ID len comment output') - self.assertEqual(self.msxClass.MSXgetIDlen(3, 3), 5, - 'Wrong get ID len comment output') - - def test_MSXgetID(self): - - self.assertEqual(self.msxClass.MSXgetID(3, 1,4), 'HOCL', - 'Wrong get ID comment output') - self.assertEqual(self.msxClass.MSXgetID(3, 2,3), 'NH3', - 'Wrong get ID comment output') - self.assertEqual(self.msxClass.MSXgetID(3, 3,5), 'NH2CL', - 'Wrong get ID comment output') - - - def test_MSXgeterror(self): - - self.assertEqual(self.msxClass.MSXgeterror(516), 'Error 516 - reference made to an illegal object index.', - 'Wrong error comment output') - self.assertEqual(self.msxClass.MSXgeterror(505), 'Error 505 - could not read hydraulic results file.', - 'Wrong error comment output') - self.assertEqual(self.msxClass.MSXgeterror(503), 'Error 503 - could not open MSX input file.', - 'Wrong error comment output') - - - def test_MSXgetparameter(self): - self.assertEqual(self.msxClass.MSXgetparameter(1,1,2), 0.076, - 'Wrong error comment output') - self.assertEqual(self.msxClass.MSXgetparameter(1, 1,4), 2.3e-3, - 'Wrong error comment output') - - def test_MSXsetparameter(self): - #set value as integer test_MSXsetparameter - self.msxClass.MSXsetparameter(1,1,1,69) - self.assertEqual(self.msxClass.MSXgetparameter(1, 1, 1), 69, - 'Wrong error comment output') - #set value as float test_MSXsetparameter - self.msxClass.MSXsetparameter(1, 1, 1, 69.420) - self.assertEqual(self.msxClass.MSXgetparameter(1, 1, 1), 69.420, - 'Wrong error comment output') - - def test_MSXgetcount(self): - #for species - self.assertEqual(self.msxClass.MSXgetcount(3), 16, - 'Wrong error get count output') - #for parameters - self.assertEqual(self.msxClass.MSXgetcount(5), 11, - 'Wrong error get count output') - #for constants - self.assertEqual(self.msxClass.MSXgetcount(6), 2, - 'Wrong error get count output') - #for patterns - self.assertEqual(self.msxClass.MSXgetcount(7), 2, - 'Wrong error get count output') - - def test_MSXgetindex(self): - #testing 4 species (number 3) first , last, 1 char & more than 1 char and middle - self.assertEqual(self.msxClass.MSXgetindex(3,"HOCL"), 1, - 'Wrong error get count output') - self.assertEqual(self.msxClass.MSXgetindex(3,"cNH2CL"), 16, - 'Wrong error get count output') - self.assertEqual(self.msxClass.MSXgetindex(3,"H"), 9, - 'Wrong error get count output') - self.assertEqual(self.msxClass.MSXgetindex(3,"OH"), 10, - 'Wrong error get count output') - #testing parameters (number 5) first , last and one middle case - self.assertEqual(self.msxClass.MSXgetindex(5, "k1"), 1, - 'Wrong error get count output') - self.assertEqual(self.msxClass.MSXgetindex(5, "kDOC2"), 11, - 'Wrong error get count output') - self.assertEqual(self.msxClass.MSXgetindex(5, "k6"), 5, - 'Wrong error get count output') - #testing constants (number 6) - self.assertEqual(self.msxClass.MSXgetindex(6, "S1"), 1, - 'Wrong error get count output') - self.assertEqual(self.msxClass.MSXgetindex(6, "S2"), 2, - 'Wrong error get count output') - #testing paterns (number 7) - self.assertEqual(self.msxClass.MSXgetindex(7, "PAT1"), 1, - 'Wrong error get count output') - self.assertEqual(self.msxClass.MSXgetindex(7, "PAT2"), 2, - 'Wrong error get count output') - - def test_MSXaddpattern(self): - - y=self.msxClass.MSXgetcount(7) - self.msxClass.MSXaddpattern("Johnnys") - self.assertEqual(self.msxClass.MSXgetcount(7), y+1, - 'Wrong error add patter output') - - def test_MSXsetpatter(self): - self.msxClass.MSXaddpattern("JohnLegend") - x = self.msxClass.MSXgetindex(7, "JohnLegend") - mult = [0.5, 0.8, 1.2, 1.0, 0.7, 0.3] - self.msxClass.MSXsetpattern(x, mult, 6) - - self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 1), 0.5, - 'Wrong set/get patternvalue comment output') - self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 2), 0.8, - 'Wrong set/get patternvalue comment output') - self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 3), 1.2, - 'Wrong set/get patternvalue comment output') - self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 4), 1.0, - 'Wrong set/get patternvalue comment output') - self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 5), 0.7, - 'Wrong set/get patternvalue comment output') - self.assertEqual(self.msxClass.MSXgetpatternvalue(x, 6), 0.3, - 'Wrong set/get patternvalue comment output') - - def test_MSXsavesmsxfile(self): - filename = "JohntheLegend.msx" - self.msxClass.MSXsavemsxfile(filename) - full_path = os.path.join(os.getcwd(), filename) - if os.path.exists(full_path): - print(f"The file {filename} exists in the current directory.") - else: - print(f"The file {filename} does not exist in the current directory.") - - - def test_MSXgetqual(self): - - #self.msxClass.MSXclose() - #self.epanetClass.unload() - inpname = os.path.join(os.getcwd(), 'epyt', 'networks', 'msx-examples', 'net2-cl2.inp') - self.epanetClass = epanet(inpname) - file_path = os.path.join(os.getcwd(), 'epyt', 'networks', 'msx-examples', 'net2-cl2.msx') - self.msxClass = epanetmsxapi(file_path) - - self.msxClass.MSXsolveH() - self.msxClass.MSXsolveQ() - t = 0 - tleft = 0 - self.msxClass.MSXinit(0) - c = 0 - while True: - t, tleft = self.msxClass.MSXstep() - c = c + 1 - if c == 1: - self.assertEqual(self.msxClass.MSXgetqual(0, 1,1), 0.8000000188349043, - 'Wrong get qual comment output') - if c == 85: - self.assertEqual(self.msxClass.MSXgetqual(0,1,1), 0.7991662288393907, - 'Wrong get qual comment output') - if c == 660: - self.assertEqual(self.msxClass.MSXgetqual(0,1,1), 0.7999999830262526, - 'Wrong get qual comment output') - if tleft <= 0: - break - - - - -if __name__ == "__main__": - unittest.main() # run all tests From cedc66d2e31cf7beda084c233b5ec8117ec81d65 Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Tue, 30 Apr 2024 06:11:08 +0300 Subject: [PATCH 08/12] updated readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bb8dc50..379ba4a 100644 --- a/README.md +++ b/README.md @@ -606,6 +606,7 @@ If you want to contribute, please check out our [Code of Conduct](https://github |setMSXConstantsValue|Assigns a new value to a specific reaction constant| |setMSXLinkInitqualValue|Assigns an initial concentration of chemical species to links| |setMSXNodeInitqualValue|Assigns an initial concentration of chemical species to nodes| +|setMSXSources|Sets the attributes of an external source of a particular chemical species to a specific node of the pipe network| |useMSXHydraulicFile|Uses a previously saved EPANET hydraulics file as the source of hydraulic information| From e040a75472dd28574f85803d880686ac2dfa89d0 Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Wed, 1 May 2024 16:11:32 +0300 Subject: [PATCH 09/12] comment for setMSXSources --- epyt/epanet.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/epyt/epanet.py b/epyt/epanet.py index 072a65b..024cee7 100644 --- a/epyt/epanet.py +++ b/epyt/epanet.py @@ -12879,6 +12879,20 @@ def setMSXLinkInitqualValue(self, value): self.msx.MSXsetinitqual(1, i+1, j+1, value[i][j]) def setMSXSources(self, nodeID, speciesID, sourcetype, concentration, patID ): + """ Sets the attributes of an external source of a particular chemical species + to a specific node of the pipe network. + + Example: + d = epanet('net2-cl2.inp'); + d.loadMSXFile('net2-cl2.msx') + srcs = d.getMSXSources() + d.addMSXPattern('PatAsIII',[2, .3, .4, 6, 5, 2, 4]) + d.setMSXSources(d.NodeNameID{2}, d.MSXSpeciesNameID{1}, Setpoint', 0.5, 'PatAsIII') % Sets the second node as setpoint. + d.setMSXSources(d.getNodeNameID(2), d.getMSXSpeciesNameID([1]),'FLOWPACED', 0.5, 'PatAsIII') + srcs = d.getMSXSources() + + See also getMSXSources, getMSXSourceNodeNameID, getMSXSourceType + getMSXSourceLevel, getMSXSourcePatternIndex.""" MSXTYPESOURCE = {'NOSOURCE', 'CONCEN', 'MASS', 'SETPOINT', 'FLOWPACED'} node = self.getNodeIndex(nodeID) species = self.getMSXSpeciesIndex(speciesID) From f5bd4966ebe6e6f93863ae521f1469861e31e3b8 Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Mon, 6 May 2024 03:30:59 +0300 Subject: [PATCH 10/12] test unit for options --- epyt/tests/test_unit_MSXOptions.py | 100 +++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 epyt/tests/test_unit_MSXOptions.py diff --git a/epyt/tests/test_unit_MSXOptions.py b/epyt/tests/test_unit_MSXOptions.py new file mode 100644 index 0000000..44f7737 --- /dev/null +++ b/epyt/tests/test_unit_MSXOptions.py @@ -0,0 +1,100 @@ +from epyt import epanet +import unittest +import os + + +class MSXtest(unittest.TestCase): + + def setUp(self): + """Call before every test case.""" + # Create EPANET object using the INP file + inpname = os.path.join(os.getcwd(), 'epyt', 'networks', 'msx-examples', 'net2-cl2.inp') + msxname = os.path.join(os.getcwd(), 'epyt', 'networks', 'msx-examples', 'net2-cl2.msx') + self.epanetClass = epanet(inpname) + self.msxClass = self.epanetClass.loadMSXFile(msxname) + + def tearDown(self): + """Call after every test case.""" + self.msxClass.MSXclose() + self.epanetClass.unload() + + """ ------------------------------------------------------------------------- """ + #new functions - Read MSX file + def test_MSXOptions(self): + self.assertEqual(self.epanetClass.getMSXTimeStep(), + (300), 'Wrong get timestep comment output') + + self.epanetClass.setMSXTimeStep(4200) + self.assertEqual(self.epanetClass.getMSXTimeStep(), + (4200), 'Wrong get timestep comment output') + + self.assertEqual(self.epanetClass.getMSXAreaUnits(), + ("FT2"), 'Wrong get Area Units comment output') + + self.epanetClass.setMSXAreaUnitsFT2() + self.assertEqual(self.epanetClass.getMSXAreaUnits(), + ("FT2"), 'Wrong get Area Units comment output') + self.epanetClass.setMSXAreaUnitsM2() + self.assertEqual(self.epanetClass.getMSXAreaUnits(), + ("M2"), 'Wrong get Area Units comment output') + self.epanetClass.setMSXAreaUnitsCM2() + self.assertEqual(self.epanetClass.getMSXAreaUnits(), + ("CM2"), 'Wrong get Area Units comment output') + + self.epanetClass.setMSXRateUnitsSEC() + self.assertEqual(self.epanetClass.getMSXRateUnits(), + ("SEC"),"Wrong get Rate Units coments output") + self.epanetClass.setMSXRateUnitsMIN() + self.assertEqual(self.epanetClass.getMSXRateUnits(), + ("MIN"), "Wrong get Rate Units coments output") + self.epanetClass.setMSXRateUnitsDAY() + self.assertEqual(self.epanetClass.getMSXRateUnits(), + ("DAY"), "Wrong get Rate Units coments output") + + self.epanetClass.setMSXSolverEUL() + self.assertEqual(self.epanetClass.getMSXSolver(), + ("EUL"), "Wrong get Solver coments output") + + self.epanetClass.setMSXSolverRK5() + self.assertEqual(self.epanetClass.getMSXSolver(), + ("RK5"), "Wrong get Solver coments output") + self.epanetClass.setMSXSolverROS2() + self.assertEqual(self.epanetClass.getMSXSolver(), + ("ROS2"), "Wrong get Solver coments output") + + self.epanetClass.setMSXCouplingFULL() + self.assertEqual(self.epanetClass.getMSXCoupling(), + ("FULL"), "Wrong get Coupling coments output") + self.epanetClass.setMSXCouplingNONE() + self.assertEqual(self.epanetClass.getMSXCoupling(), + ("NONE"), "Wrong get Coupling coments output") + + self.epanetClass.setMSXCompilerVC() + self.assertEqual(self.epanetClass.getMSXCompiler(), + ("VC"), "Wrong get Compiler coments output") + self.epanetClass.setMSXCompilerGC() + self.assertEqual(self.epanetClass.getMSXCompiler(), + ("GC"), "Wrong get Compiler coments output") + self.epanetClass.setMSXCompilerNONE() + self.assertEqual(self.epanetClass.getMSXCompiler(), + ("NONE"), "Wrong get Compiler coments output") + + self.epanetClass.setMSXAtol(0.2) + self.assertEqual(self.epanetClass.getMSXAtol(), + (0.2), "Wrong get ATOL coments output") + self.epanetClass.setMSXRtol(0.2) + self.assertEqual(self.epanetClass.getMSXRtol(), + (0.2), "Wrong get RTOL coments output") + + + def test_Parameters(self): + self.assertEqual(self.epanetClass.getMSXEquationsTerms(), + (["Kf 1.5826e-4 * RE^0.88 / D"]), 'Wrong get Equations comment output') + self.assertEqual(self.epanetClass.getMSXEquationsPipes(), + (["RATE CL2 -Kb*CL2 - (4/D)*Kw*Kf/(Kw+Kf)*CL2"]), 'Wrong get Equations comment output') + self.assertEqual(self.epanetClass.getMSXEquationsTanks(), + (["RATE CL2 -Kb*CL2"]), 'Wrong get Equations comment output') + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From 5c4516bcf2938bf9991831e8cc199941d20a248b Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Mon, 6 May 2024 06:31:03 +0300 Subject: [PATCH 11/12] function writeMSXFile --- epyt/epanet.py | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/epyt/epanet.py b/epyt/epanet.py index 024cee7..e8fe012 100644 --- a/epyt/epanet.py +++ b/epyt/epanet.py @@ -11203,6 +11203,10 @@ def loadMSXFile(self, msxname, customMSXlib=None, ignore_properties=False): copyfile(msxname, self.msxname) self.msx = epanetmsxapi(self.msxname, customMSXlib=customMSXlib) + + + + #message to user if he uses ph with msx if self.api._ph is not None: print("In order for LoadMSX to work remove from epanet the ph") @@ -12929,6 +12933,104 @@ def setMSXNodeInitqualValue(self, value): for i in range(len(value)): for j in range(len(value[0])): self.msx.MSXsetinitqual(0, i+1, j+1, value[i][j]) + def setMSXWrite(self): + value = EpytValues() + value.FILENAME = "" + value.TITLE = "" + value.AREA_UNITS = "" + value.RATE_UNITS = "" + value.SOLVER = "" + value.TIMESTEP = {} + value.COMPILER = "" + value.COUPLING = "" + value.RTOL = {} + value.ATOL = {} + + value.SPECIES = {} + value.COEFFICIENTS = {} + value.TERMS = {} + value.PIPES = {} + value.TANKS = {} + value.SOURCES = {} + value.GLOBAL = {} + value.QUALITY = {} + value.PARAMETERS = {} + value.PATERNS = {} + + + return value + def writeMSXFile(self, msx): + filename = msx.FILENAME + with open(filename, 'w')as f: + f.write("[TITLE]\n") + f.write(msx.TITLE) + #OPTIONS + f.write("\n\n[OPTIONS]") + ans = msx.AREA_UNITS + f.write("\nAREA_UNITS\t{}".format(ans)) + ans = msx.RATE_UNITS + f.write("\nRATE_UNITS\t{}".format(ans)) + ans = msx.SOLVER + f.write("\nSOLVER\t\t{}".format(ans)) + ans = msx.TIMESTEP + f.write("\nTIMESTEP\t{}".format(ans)) + ans = msx.COMPILER + f.write("\nCOMPILER\t{}".format(ans)) + ans = msx.COUPLING + f.write("\nCOUPLING\t{}".format(ans)) + ans = msx.RTOL + f.write("\nRTOL\t\t{}".format(ans)) + ans = msx.ATOL + f.write("\nATOL\t\t{}".format(ans)) + + + f.write("\n\n[SPECIES]\n") + ans = list(msx.SPECIES) + for item in ans: + f.write("{}\n".format(item)) + + f.write("\n\n[COEFFICIENTS]\n") + ans = list(msx.COEFFICIENTS) + for item in ans: + f.write("{}\n".format(item)) + f.write("\n\n[TERMS]\n") + ans = list(msx.TERMS) + for item in ans: + f.write("{}\n".format(item)) + f.write("\n\n[PIPES]\n") + ans = list(msx.PIPES) + for item in ans: + f.write("{}\n".format(item)) + f.write("\n\n[TANKS]\n") + ans = list(msx.TANKS) + for item in ans: + f.write("{}\n".format(item)) + f.write("\n\n[SOURCES]\n") + ans = list(msx.SOURCES) + for item in ans: + f.write("{}\n".format(item)) + f.write("\n\n[QUALITY]\n") + ans = list(msx.QUALITY) + for item in ans: + f.write("{}\n".format(item)) + f.write("\n\n[GLOBAL]\n") + ans = list(msx.GLOBAL) + for item in ans: + f.write("{}\n".format(item)) + f.write("\n\n[PARAMETERS]\n") + ans = list(msx.PARAMETERS) + for item in ans: + f.write("{}\n".format(item)) + f.write("\n\n[PATTERNS]\n") + ans = list(msx.PATERNS) + for item in ans: + f.write("{}\n".format(item)) + + + f.write('\n[REPORT]\n') + f.write('NODES ALL\n') + f.write('LINKS ALL\n') + class epanetapi: """ From f3e8ed412b26279fa88e1fc204426ebd1769ce9a Mon Sep 17 00:00:00 2001 From: ichrys03 <79056704+ichrys03@users.noreply.github.com> Date: Mon, 6 May 2024 06:39:48 +0300 Subject: [PATCH 12/12] updated readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 379ba4a..fc32a51 100644 --- a/README.md +++ b/README.md @@ -531,6 +531,7 @@ If you want to contribute, please check out our [Code of Conduct](https://github |loadMSXFile|Opens the EPANET-MSX toolkit system| |unloadMSX|Closes the EPANET-MSX toolkit system| |addMSXPattern|Adds a new, empty MSX source time pattern to the project| +|writeMSXFile|Write a new MSX file| |initializeMSXQualityAnalysis|Initializes the MSX system before solving for water quality results in step-wise fashion| |getMSXComputedQualitySpecie|Retrieves the quality values for specific specie (e.g getMSXComputedQualitySpecie('CL2'))| |getMSXComputedLinkQualitySpecie|Returns the link quality for specific specie|