3.3 EPANET (Examples 3-5) using the Toolkit#

Purpose#

This section continues the demonstration of the various previous examples using the Toolkit to run the example and make changes to inputs and rerun the examples. The main concept is that the Toolkit allows manipulation of models independent of a GUI which when combined with either Toolkit supplied control rules, or external “control” lets one model and interpret (assuming IF-THEN interpretation is amenable) many changes automatically.

Installation Notes#

The examples herein are run on the developmental computer (a Raspberry Pi). The scripts should work fine on another computer with the toolkit installed (Windows probably takes a bit more fussing to get the Linux subsystem to call to the Toolkit).

Example 3 : Three-Reservoir-Problem#

This example is a the classic hydraulics problem, that appears in some form in most if not all hydraulics textbooks; here we will use the already built input file - and note we wont use any of the basemap capabilities, as the Toolkit is not really intended for such direct graphics.

Recall the problem statement:

Reservoirs A, B, and C are connected as shown. The water elevations in reservoirs A, B, and C are 100 m, 80 m, and 60 m. The three pipes connecting the reservoirs meet at junction J, with pipe AJ being 900 m long, BJ being 800 m long, and CJ being 700 m long. The diameters of all the pipes are 850 mm. If all the pipes are ductile iron, and the water temperature is 293\(^o\)K, find the direction and magnitude of flow in each pipe.

The input file from earlier is copiec to our work directory; let’s list it

! cat ./ex3-tk/EX3.inp
[TITLE]





[JUNCTIONS]

;ID              	Elev        	Demand      	Pattern         

 NodeA           	0           	0           	                	;

 NodeB           	0           	0           	                	;

 NodeC           	0           	0           	                	;

 J               	110         	0           	                	;



[RESERVOIRS]

;ID              	Head        	Pattern         

 A               	100         	                	;

 B               	80          	                	;

 C               	60          	                	;



[TANKS]

;ID              	Elevation   	InitLevel   	MinLevel    	MaxLevel    	Diameter    	MinVol      	VolCurve        	Overflow



[PIPES]

;ID              	Node1           	Node2           	Length      	Diameter    	Roughness   	MinorLoss   	Status

 PAJ             	NodeA           	J               	900         	850         	0.1         	0           	Open  	;

 PBJ             	NodeB           	J               	800         	850         	0.1         	0           	Open  	;

 PJC             	J               	NodeC           	700         	850         	0.1         	0           	Open  	;

 4               	A               	NodeA           	10          	2400        	0.1         	0           	Open  	;

 5               	B               	NodeB           	10          	2400        	0.1         	0           	Open  	;

 6               	C               	NodeC           	10          	2400        	0.1         	0           	Open  	;



[PUMPS]

;ID              	Node1           	Node2           	Parameters



[VALVES]

;ID              	Node1           	Node2           	Diameter    	Type	Setting     	MinorLoss   



[TAGS]



[DEMANDS]

;Junction        	Demand      	Pattern         	Category



[STATUS]

;ID              	Status/Setting



[PATTERNS]

;ID              	Multipliers



[CURVES]

;ID              	X-Value     	Y-Value



[CONTROLS]



[RULES]



[ENERGY]

 Global Efficiency  	75

 Global Price       	0

 Demand Charge      	0



[EMITTERS]

;Junction        	Coefficient



[QUALITY]

;Node            	InitQual



[SOURCES]

;Node            	Type        	Quality     	Pattern



[REACTIONS]

;Type     	Pipe/Tank       	Coefficient





[REACTIONS]

 Order Bulk            	1

 Order Tank            	1

 Order Wall            	1

 Global Bulk           	0

 Global Wall           	0

 Limiting Potential    	0

 Roughness Correlation 	0



[MIXING]

;Tank            	Model



[TIMES]

 Duration           	0

 Hydraulic Timestep 	1:00

 Quality Timestep   	0:05

 Pattern Timestep   	1:00

 Pattern Start      	0:00

 Report Timestep    	1:00

 Report Start       	0:00

 Start ClockTime    	12 am

 Statistic          	None



[REPORT]

 Status             	No

 Summary            	No

 Page               	0



[OPTIONS]

 Units              	LPS

 Headloss           	H-W

 Specific Gravity   	1

 Viscosity          	1

 Trials             	40

 Accuracy           	0.001

 CHECKFREQ          	2

 MAXCHECK           	10

 DAMPLIMIT          	0

 Unbalanced         	Continue 10

 Pattern            	1

 Demand Multiplier  	1.0

 Emitter Exponent   	0.5

 Quality            	None mg/L

 Diffusivity        	1

 Tolerance          	0.01



[COORDINATES]

;Node            	X-Coord           	Y-Coord

NodeA           	1177.043          	8793.774          

NodeB           	5340.467          	7782.101          

NodeC           	8200.389          	5719.844          

J               	4659.533          	6186.770          

A               	457.198           	9046.693          

B               	4659.533          	8093.385          

C               	8375.486          	6089.494          



[VERTICES]

;Link            	X-Coord           	Y-Coord

PAJ             	1643.969          	8618.677          

PAJ             	2149.805          	8307.393          

PAJ             	2519.455          	7762.646          

PAJ             	2947.471          	7198.444          

PAJ             	3161.479          	6809.339          

PAJ             	3492.218          	6536.965          

PAJ             	3822.957          	6361.868          

PAJ             	4309.339          	6206.226          

PBJ             	5749.027          	7762.646          

PBJ             	6060.311          	7723.735          

PBJ             	6215.953          	7607.004          

PBJ             	6196.498          	7431.907          

PBJ             	5787.938          	7062.257          

PBJ             	5301.556          	6673.152          

PJC             	5340.467          	6167.315          

PJC             	6118.677          	6050.584          

PJC             	6702.335          	5856.031          

PJC             	7227.626          	5700.389          

PJC             	7636.187          	5680.934          



[LABELS]

;X-Coord             Y-Coord             Label & Anchor Node



[BACKDROP]

  DIMENSIONS  	0.000             	0.000             	10000.000         	10000.000         

 UNITS          	None

 FILE           	

 OFFSET         	0.00            	0.00            



[END]

Now we will run it as supplied, then modify using the Toolkit for more useful purposes.

import epamodule as em  # import the package
#Open the EPANET toolkit & hydraulics solver   
em.ENopen("./ex3-tk/EX3.inp", "./ex3-tk/EX3-tk.rpt")
# build report command strings Keyword  Action see user manual
#command0 = "Status     Yes"
command1 = "Summary            	Yes"
command2 = "Nodes            	ALL"
command3 = "Links            	ALL"
em.ENsetstatusreport(2) # full status report
#em.ENsetreport(command0)
em.ENsetreport(command1)
em.ENsetreport(command2)
em.ENsetreport(command3)
em.ENsaveinpfile("./ex3-tk/EX3-tk.inp") #overwrite the input file
em.ENclose()
# now run from the new file
em.ENopen("./ex3-tk/EX3-tk.inp", "./ex3-tk/EX3-tk.rpt")
em.ENopenH()
em.ENsolveH()
em.ENsaveH() # need to save to a binary file before write
em.ENcloseH()
em.ENopenQ()
em.ENsolveQ()
em.ENreport() # now write report
# Close hydraulics solver & toolkit */
em.ENclose()
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
/tmp/ipykernel_219785/2226040250.py in <module>
----> 1 import epamodule as em  # import the package
      2 #Open the EPANET toolkit & hydraulics solver
      3 em.ENopen("./ex3-tk/EX3.inp", "./ex3-tk/EX3-tk.rpt")
      4 # build report command strings Keyword  Action see user manual
      5 #command0 = "Status     Yes"

~/ects-epanet/ects-epanet-notes/lessons/lesson03/epamodule.py in <module>
     10 _plat= platform.system()
     11 if _plat=='Linux':
---> 12   _lib = ctypes.CDLL("./libepanet2.so") # For My Raspberry Pi
     13 ##  _lib = ctypes.CDLL("./en2tools.so.1.5.0")
     14 ##  _lib = ctypes.CDLL("./epanet2toolkit.so")

/usr/lib/python3.8/ctypes/__init__.py in __init__(self, name, mode, handle, use_errno, use_last_error, winmode)
    371 
    372         if handle is None:
--> 373             self._handle = _dlopen(self._name, mode)
    374         else:
    375             self._handle = handle

OSError: ./libepanet2.so: cannot open shared object file: No such file or directory
# Check the output
! cat ./ex3-tk/EX3-tk.rpt
  Page 1                                    Sat Jul 29 08:57:04 2023

  ******************************************************************
  *                           E P A N E T                          *
  *                   Hydraulic and Water Quality                  *
  *                   Analysis for Pipe Networks                   *
  *                         Version 2.2                            *
  ******************************************************************
  
   
      Input Data File ................... ./ex3-tk/EX3-tk.inp
      Number of Junctions................ 4
      Number of Reservoirs............... 3
      Number of Tanks ................... 0
      Number of Pipes ................... 6
      Number of Pumps ................... 0
      Number of Valves .................. 0
      Headloss Formula .................. Hazen-Williams
      Nodal Demand Model ................ DDA
      Hydraulic Timestep ................ 1.00 hrs
      Hydraulic Accuracy ................ 0.001000
      Status Check Frequency ............ 2
      Maximum Trials Checked ............ 10
      Damping Limit Threshold ........... 0.000000
      Maximum Trials .................... 40
      Quality Analysis .................. None
      Specific Gravity .................. 1.00
      Relative Kinematic Viscosity ...... 1.00
      Relative Chemical Diffusivity ..... 1.00
      Demand Multiplier ................. 1.00
      Total Duration .................... 0.00 hrs
      Reporting Criteria:
         All Nodes
         All Links
   
  Analysis begun Sat Jul 29 08:57:04 2023

   
  Hydraulic Status:
  -----------------------------------------------------------------------
     0:00:00: Balancing the network:

              Trial  1: relative flow change = 10.124589
              Trial  2: relative flow change = 1.170853
              Trial  3: relative flow change = 1.161766
              Trial  4: relative flow change = 1.124854
              Trial  5: relative flow change = 0.990238
              Trial  6: relative flow change = 0.644312
              Trial  7: relative flow change = 0.226544
              Trial  8: relative flow change = 0.048396
              Trial  9: relative flow change = 0.002497
              Trial 10: relative flow change = 0.000007
                        maximum  flow change = 0.0000 for Link PBJ
                        maximum  head error  = 0.0000 for Link PBJ

     0:00:00: Balanced after 10 trials
     0:00:00: Reservoir A is emptying
     0:00:00: Reservoir B is emptying
     0:00:00: Reservoir C is filling
   
   
  Node Results:
  ----------------------------------------------
                     Demand      Head  Pressure
  Node                  L/s         m         m
  ----------------------------------------------
  NodeA                0.00    100.00    100.00
  NodeB                0.00     80.00     80.00
  NodeC                0.00     60.00     60.00
  J                    0.00     79.63    -30.37
  A                   -2.35    100.00     -0.00  Reservoir
  B                   -0.29     80.00      0.00  Reservoir
  C                    2.64     60.00     -0.00  Reservoir
   
   
  Link Results:
  ----------------------------------------------
                       Flow  Velocity  Headloss
  Link                  L/s       m/s    /1000m
  ----------------------------------------------
  PAJ                  2.35      0.00     22.63
  PBJ                  0.29      0.00      0.46
  PJC                  2.64      0.00     28.04
  4                    2.35      0.00      0.14
  5                    0.29      0.00      0.00
  6                   -2.64      0.00      0.18
   
  Analysis ended Sat Jul 29 08:57:04 2023

Nice! Seems like we have kind of got the hang of the Toolkit.

Note

In class we will draw the actual network simulated above - notice the three extra links, we put these there intentionally (check the video), to be able to interpret pressures at Nodes A,B,C, and J. In the above example, Nodes A,B, and C are all at zero elevation. Node J is at 110 - so any flow towards J must be uphill. Lets use the toolbox to help us find the elevation Node J would need to be, to have a pressure of +1 meters.

First lets manipulate Node J elevation to produce a pressure of 0.

import epamodule as em  # import the package
#Open the EPANET toolkit & hydraulics solver   
em.ENopen("./ex3-tk/EX3-tk.inp", "./ex3-tk/EX3-tk.rpt") # The modified file
# build report command strings Keyword  Action see user manual
#command0 = "Status     Yes"
#command1 = "Summary            	Yes"
#command2 = "Nodes            	ALL"
#command3 = "Links            	ALL"
#em.ENsetstatusreport(2) # full status report
#em.ENsetreport(command0)
#em.ENsetreport(command1)
#em.ENsetreport(command2)
#em.ENsetreport(command3)
#em.ENsaveinpfile("./ex3-tk/EX3-tk.inp") #overwrite the input file
#em.ENclose()
# now run from the new file
#em.ENopen("./ex3-tk/EX3-tk.inp", "./ex3-tk/EX3-tk.rpt")
em.ENopenH()
nodej = em.ENgetnodeindex("J") # Get the index of Node J in the internal database
elevj = em.ENgetnodevalue(nodej,0)
# wrap this into a little search loop
em.ENsetnodevalue(nodej, 0, elevj) # set nodej to elevation (code 0) of 100.0
em.ENsolveH()
presj = em.ENgetnodevalue(nodej,11)
print("Initial Values")
print("Elevation J: " + str(round(elevj,3)) + " Pressure J: " + str(round(presj,3)) )
# Lets do a crude search
tol = 1e-3
for iter in range(100):
    if abs(presj) <= tol:
        print("tolerance met",iter)
        break
    if presj < 0.0 :
        elevj = elevj*0.99
    if presj > 0.0 :
        elevj = elevj*1.01
    em.ENsetnodevalue(nodej, 0, elevj) # set nodej to elevation (code 0) of 100.0 
    em.ENsolveH()
    presj = em.ENgetnodevalue(nodej,11)
print("Elevation J: " + str(round(elevj,3)) + " Pressure J: " + str(round(presj,3)) )
# end search
em.ENsaveH() # need to save to a binary file before write
em.ENcloseH()
em.ENopenQ()
em.ENsolveQ()
em.ENreport() # now write report
# Close hydraulics solver & toolkit */
em.ENclose()
Initial Values
Elevation J: 110.0 Pressure J: -30.371
tolerance met 62
Elevation J: 79.628 Pressure J: 0.0

Now we modify for the target pressure, supplied as a variable - obviously searching as illustrated is terribly inefficient, but does illustrate the utility of the toolkit. We are using the computer to make adjustments and test outputs rather than doing it ourselves using the GUI; for a complex problem, its far faster to do such exercises programmatically rather then trial-and-error in a GUI.

import epamodule as em  # import the package
#Open the EPANET toolkit & hydraulics solver   
em.ENopen("./ex3-tk/EX3-tk.inp", "./ex3-tk/EX3-tk.rpt") # The modified file
em.ENopenH()
nodej = em.ENgetnodeindex("J") # Get the index of Node J in the internal database
elevj = em.ENgetnodevalue(nodej,0)
# wrap this into a little search loop
em.ENsetnodevalue(nodej, 0, elevj) # set nodej to elevation (code 0) of 100.0
em.ENsolveH()
presj = em.ENgetnodevalue(nodej,11)
print("Initial Values")
print("Elevation J: " + str(round(elevj,3)) + " Pressure J: " + str(round(presj,3)) )
# Lets do a crude search
tol = 1e-3
targetp = 1.0
for iter in range(1000):
    if abs(presj-targetp) <= tol:
        print("tolerance met",iter)
        break
    if presj < targetp :
        elevj = elevj*0.99
    if presj > targetp :
        elevj = elevj*1.11
    em.ENsetnodevalue(nodej, 0, elevj) # set nodej to elevation (code 0) of 100.0 
    em.ENsolveH()
    presj = em.ENgetnodevalue(nodej,11)
print(str(iter) + " Elevation J: " + str(round(elevj,3)) + " Pressure J: " + str(round(presj,3)) )
# end search
em.ENsaveH() # need to save to a binary file before write
em.ENcloseH()
em.ENopenQ()
em.ENsolveQ()
em.ENreport() # now write report
# Close hydraulics solver & toolkit */
em.ENclose()
Initial Values
Elevation J: 110.0 Pressure J: -30.371
tolerance met 318
318 Elevation J: 78.628 Pressure J: 1.0

Exercise#

A better way for the example above would be some version of bisection. Modify the script to search for the desired elevation using bisection; select a reasonable tolerance to stop. You may find Chat-GPT 4.0 useful to construct a working script.

A bisection solver could be adapted from Cleveland, T.G. (2022) Hydraulic System Design JupyterBook notes to accompany CE 4353/CE 5360 at TTU; Example 1 in specific energy section

Example 4 - A simple looped network#

Expanding the examples, we will next consider a looped network. As before we will use an exercise as the motivating example.

Problem Statement

The water-supply network shown in Figure 61 has constant-head elevated storage tanks at A and C, with inflow and outflow at B and D. The network is on flat terrain with node elevations all equal to 50 meters. If all pipes are ductile iron, compute the inflows/outflows to the storage tanks. Assume that flow in all pipes are fully turbulent.

As before we will use the previously prepared input file and modify to explore the Toolkit. By this point its legitimately a lot of cut and paste.

import epamodule as em  # import the package
#Open the EPANET toolkit & hydraulics solver   
em.ENopen("./ex4-tk/EX4-JB.inp", "./ex4-tk/EX4-tk.rpt")
# build report command strings Keyword  Action see user manual
command0 = "Status     Yes"
command1 = "Summary            	Yes"
command2 = "Nodes            	ALL"
command3 = "Links            	ALL"
em.ENsetstatusreport(2) # full status report
em.ENsetreport(command0)
em.ENsetreport(command1)
em.ENsetreport(command2)
em.ENsetreport(command3)
em.ENsaveinpfile("./ex4-tk/EX4-tk.inp") #overwrite the input file
em.ENclose()
# now run from the new file
em.ENopen("./ex4-tk/EX4-tk.inp", "./ex4-tk/EX4-tk.rpt")
em.ENopenH()
em.ENsolveH()
em.ENsaveH() # need to save to a binary file before write
em.ENcloseH()
em.ENopenQ()
em.ENsolveQ()
em.ENreport() # now write report
# Close hydraulics solver & toolkit */
em.ENclose()

! cat ./ex4-tk/EX4-tk.rpt
  Page 1                                    Sat Jul 29 10:32:27 2023

  ******************************************************************
  *                           E P A N E T                          *
  *                   Hydraulic and Water Quality                  *
  *                   Analysis for Pipe Networks                   *
  *                         Version 2.2                            *
  ******************************************************************
  
   
      Input Data File ................... ./ex4-tk/EX4-tk.inp
      Number of Junctions................ 4
      Number of Reservoirs............... 2
      Number of Tanks ................... 0
      Number of Pipes ................... 6
      Number of Pumps ................... 0
      Number of Valves .................. 0
      Headloss Formula .................. Darcy-Weisbach
      Nodal Demand Model ................ DDA
      Hydraulic Timestep ................ 1.00 hrs
      Hydraulic Accuracy ................ 0.001000
      Status Check Frequency ............ 2
      Maximum Trials Checked ............ 10
      Damping Limit Threshold ........... 0.000000
      Maximum Trials .................... 40
      Quality Analysis .................. None
      Specific Gravity .................. 1.00
      Relative Kinematic Viscosity ...... 1.00
      Relative Chemical Diffusivity ..... 1.00
      Demand Multiplier ................. 1.00
      Total Duration .................... 0.00 hrs
      Reporting Criteria:
         All Nodes
         All Links
   
  Analysis begun Sat Jul 29 10:32:27 2023

   
  Hydraulic Status:
  -----------------------------------------------------------------------
     0:00:00: Balanced after 5 trials
     0:00:00: Reservoir 1 is emptying
     0:00:00: Reservoir 2 is filling
   
   
  Node Results:
  ----------------------------------------------
                     Demand      Head  Pressure
  Node                  L/s         m         m
  ----------------------------------------------
  3                    0.00     75.00     25.00
  4                 -200.00     79.97     29.97
  5                    0.00     70.00     20.00
  6                  200.00     69.90     19.90
  1                 -121.21     75.00     -0.00  Reservoir
  2                  121.21     70.00      0.00  Reservoir
   
   
  Link Results:
  ----------------------------------------------
                       Flow  Velocity  Headloss
  Link                  L/s       m/s    /1000m
  ----------------------------------------------
  1                  121.21      0.19      0.04
  2                 -121.21      0.19      0.04
  3                  -63.45      1.29      7.10
  4                  136.55      1.93     12.47
  5                   15.34      0.16      0.09
  6                  184.66      1.47      5.10
   
  Analysis ended Sat Jul 29 10:32:27 2023

Now lets use some of the tools to get more than one thing. First we will get the count of some objects, then we will change the diameter of one pipe and examine the effect. Notice how we can repeatedly change things and rerun the hydraulic module (as above) almost without effort using the Toolkit.

#ENgetcount(countcode)

import epamodule as em  # import the package
#Open the EPANET toolkit & hydraulics solver   
em.ENopen("./ex4-tk/EX4-tk.inp", "./ex4-tk/EX4-tk.rpt")
howmanynodes = em.ENgetcount(0) # Code 0 == nodes
howmanylinks = em.ENgetcount(2) # Code 2 == links
howmanyFGN   = em.ENgetcount(1) # Code 1 == Tanks/Reservoirs
print(" System Topology is:\n")
print(" Node count: " + str(howmanynodes))
print(" Link count: " + str(howmanylinks))
print(" FGN count : " + str(howmanyFGN))
diameter = [] # create empty list
for ilink in range(howmanylinks):
    diameter.append(em.ENgetlinkvalue(ilink+1,0)) # Code 0 == diameter
    print("Link :" + str(ilink+1) + " Diameter(mm) : " + str(diameter[ilink]))
em.ENopenH()
em.ENsolveH()
hloss = [] # create empty list
for ilink in range(howmanylinks):
    hloss.append(em.ENgetlinkvalue(ilink+1,10)) # Code 10 == head loss
    print("Link :" + str(ilink+1) + " Head loss (m/1000m) : " + str(round(hloss[ilink],4)))
print("Change diameter link 4")
em.ENsetlinkvalue(4, 0, 100)
diameter = [] # create empty list
for ilink in range(howmanylinks):
    diameter.append(em.ENgetlinkvalue(ilink+1,0)) # Code 0 == diameter
    print("Link :" + str(ilink+1) + " Diameter(mm) : " + str(diameter[ilink]))
em.ENsolveH()
nhloss = [] # create empty list
for ilink in range(howmanylinks):
    nhloss.append(em.ENgetlinkvalue(ilink+1,10)) # Code 10 == head loss
    print("Link :" + str(ilink+1) + " Head loss (m/1000m) : " + str(round(nhloss[ilink],4)))
em.ENsaveH() # need to save to a binary file before write
em.ENcloseH()
em.ENopenQ()
em.ENsolveQ()
em.ENreport() # now write report
# Close hydraulics solver & toolkit */
em.ENclose()
 System Topology is:

 Node count: 6
 Link count: 6
 FGN count : 2
Link :1 Diameter(mm) : 900.0
Link :2 Diameter(mm) : 900.0
Link :3 Diameter(mm) : 250.0
Link :4 Diameter(mm) : 300.0
Link :5 Diameter(mm) : 350.0
Link :6 Diameter(mm) : 400.0
Link :1 Head loss (m/1000m) : 0.0004
Link :2 Head loss (m/1000m) : 0.0004
Link :3 Head loss (m/1000m) : 4.973
Link :4 Head loss (m/1000m) : 9.9723
Link :5 Head loss (m/1000m) : 0.1026
Link :6 Head loss (m/1000m) : 5.1018
Change diameter link 4
Link :1 Diameter(mm) : 900.0
Link :2 Diameter(mm) : 900.0
Link :3 Diameter(mm) : 250.0
Link :4 Diameter(mm) : 100.0
Link :5 Diameter(mm) : 350.0
Link :6 Diameter(mm) : 400.0
Link :1 Head loss (m/1000m) : 0.0
Link :2 Head loss (m/1000m) : 0.0
Link :3 Head loss (m/1000m) : 40.4552
Link :4 Head loss (m/1000m) : 45.4552
Link :5 Head loss (m/1000m) : 0.1024
Link :6 Head loss (m/1000m) : 5.1024

Exercise#

Change the parameter code to recover flow instead of head loss and rerun the example, what effect does shrinking pipe 4 have on flow rate?

Example 5 - Simulating a Pump#

This example repeats the same problem as before, but using the Toolkit to load and run the model. A bit of the earlier example is replicated below:

Figure XX is a conceptual model of a pump lifting water through a 100 mm diameter, 100 meter long, ductile iron pipe from a lower elevation reservoir to an upper reservoir.



The suction side of the pump is a 100 mm diameter, 4-meter long ductile iron pipe. The difference in reservoir free-surface elevations is 10 meters.

The pump performance curve is given as $\(hp = 15.0-0.1Q^2 \)$ where the added head is in meters and the flow rate is in liters per second (lps). The analysis goal is to estimate the flow rate in the system.

To use the Toolkit we more or less just repeat from the above examples, here I run the entire simulation as some adjustments are left as exercises.

import epamodule as em  # import the package
# Run a complete simulation. input file must already exist
em.ENepanet("./ex5-tk/EX5-tk.inp", "./ex5-tk/EX5-tk.rpt") 
# Print the output report (it will be sparse)
!cat ./ex5-tk/EX5-tk.rpt
  Page 1                                    Sun Jul 30 15:32:30 2023

  ******************************************************************
  *                           E P A N E T                          *
  *                   Hydraulic and Water Quality                  *
  *                   Analysis for Pipe Networks                   *
  *                         Version 2.2                            *
  ******************************************************************
  
  Analysis begun Sun Jul 30 15:32:30 2023

  Analysis ended Sun Jul 30 15:32:30 2023

Exercise#

Use the Toolkit to modify the input file (EX5-tk) to produce a more useful output file.

# one possible solution
import epamodule as em  # import the package
#Open the EPANET toolkit & hydraulics solver   
em.ENopen("./ex5-tk/EX5-tk.inp", "./ex5-tk/EX5-tk.rpt")
# build report command strings Keyword  Action see user manual
command0 = "Status     Yes"
command1 = "Summary            	Yes"
command2 = "Nodes            	ALL"
command3 = "Links            	ALL"
em.ENsetstatusreport(2) # full status report
em.ENsetreport(command0)
em.ENsetreport(command1)
em.ENsetreport(command2)
em.ENsetreport(command3)
em.ENsaveinpfile("./ex5-tk/EX5-tkmod.inp") #overwrite the input file
em.ENclose()
# now run from the new file
em.ENepanet("./ex5-tk/EX5-tkmod.inp", "./ex5-tk/EX5-tkmod.rpt")
! cat ./ex5-tk/EX5-tkmod.rpt

Exercise#

Modify the upstream pool elevation so it is at 14.999 meters. The pump flowrate should go down a lot (but not to zero).

# one possible solution
import epamodule as em  # import the package
#Open the EPANET toolkit & hydraulics solver   
em.ENopen("./ex5-tk/EX5-tkmod.inp", "./ex5-tk/EX5-tkmod.rpt")
# The upper reservoir is Node 2 in the input file
nodej = em.ENgetnodeindex("2") # Get the index of Node 2 in the internal database
elevj = em.ENgetnodevalue(nodej,0) # Get the elevation and check
print("Internal Node: ",nodej," Initial Head: ",round(elevj,3))
elevj=24.9999 # Change so thet DeltaH is 14.999
print("Increase Head to ", round(elevj,3))
em.ENsetnodevalue(nodej,0,elevj)
em.ENsaveinpfile("./ex5-tk/EX5-tkmod.inp") #overwrite the input file
em.ENclose()
# now run from the new file
em.ENepanet("./ex5-tk/EX5-tkmod.inp", "./ex5-tk/EX5-tkmod.rpt")
! cat ./ex5-tk/EX5-tkmod.rpt

Exercise#

Now modify the pump curve to approximately recover the flowrate.

Warning

At the time of writing, pump curves are edited outside of the Toolkit - you would search the input file for the section

[CURVES]
;ID              	X-Value     	Y-Value
;PUMP: 
 1               	0           	15          
 1               	1           	14.9        
 1               	10          	5   

Then edit the indicated curve - for this exercise, manual edits would be OK.

Note

Probably just do this in class and leave the file on the server

Files#

The files used in the above examples are located at:

  1. Example 3 Files

  2. Example 4 Files

  3. Example 5 Files