Network and Network Components

In OOPNET, everything is about the Network class. A network is the object-oriented representation of a hydraulic water distribution system model. It contains all the information stored in a EPANET input file and can be easily manipulated, accessed, simulated and plotted.

In this guide, we will take a look at the network class, the individual components stored in it and how to interact with them.

Creating a Network

The network acts as a container for all network components, settings etc. that you can find in an EPANET model. You can create a new, empty model:

import oopnet as on

blank_network = on.Network()

Alternatively, you can read an EPANET input file and create a network from it. OOPNET supports both EPANET 2.0 and 2.2 models. For instance, we can read a saved model - in this example the model by Poulakis et al. - using the network’s read() method. We recommend using the os library for specifying the file path:

import os

import oopnet as on
filename = os.path.join('data', 'Poulakis.inp')
network = on.Network.read(filename)
_images/adders_and_removers_1.png

Writing an Input File

Writing a network object to an EPANET input file is very easy. Just use the network’s write() method:

network.write('new_model.inp')

Network Components

A network contains objects representing the different model components:

Getter Functions

To access the individual components in the model, OOPNET provides utility functions like get_junction() to get a single Junction by its ID, while functions like get_pumps() returns a list of all Pump objects. If you want a list of all IDs of objects of a certain type stored in a network, you can use functions like get_node_ids(). Take a look at the getters module for a complete list of all available getter functions.

As an example, we can iterate over all junctions in the network and print their demands and elevations in the console:

for j in on.get_junctions(network):
    print(j, j.demand, j.elevation)

This results in an output like this:

Junction(id='J-02', comment=None, tag=None, xcoordinate=500.0, ycoordinate=7500.0, elevation=0.0, initialquality=0.0, sourcequality=0.0, sourcetype=None, strength=0.0, sourcepattern=None, emittercoefficient=0.0, demandpattern=None, demand=50.0) 50.0 0.0
Junction(id='J-03', comment=None, tag=None, xcoordinate=500.0, ycoordinate=7000.0, elevation=0.0, initialquality=0.0, sourcequality=0.0, sourcetype=None, strength=0.0, sourcepattern=None, emittercoefficient=0.0, demandpattern=None, demand=50.0) 50.0 0.0
Junction(id='J-04', comment=None, tag=None, xcoordinate=500.0, ycoordinate=6500.0, elevation=0.0, initialquality=0.0, sourcequality=0.0, sourcetype=None, strength=0.0, sourcepattern=None, emittercoefficient=0.0, demandpattern=None, demand=50.0) 50.0 0.0
Junction(id='J-05', comment=None, tag=None, xcoordinate=500.0, ycoordinate=6000.0, elevation=0.0, initialquality=0.0, sourcequality=0.0, sourcetype=None, strength=0.0, sourcepattern=None, emittercoefficient=0.0, demandpattern=None, demand=50.0) 50.0 0.0
Junction(id='J-06', comment=None, tag=None, xcoordinate=500.0, ycoordinate=5500.0, elevation=0.0, initialquality=0.0, sourcequality=0.0, sourcetype=None, strength=0.0, sourcepattern=None, emittercoefficient=0.0, demandpattern=None, demand=50.0) 50.0 0.0
Junction(id='J-07', comment=None, tag=None, xcoordinate=500.0, ycoordinate=5000.0, elevation=0.0, initialquality=0.0, sourcequality=0.0, sourcetype=None, strength=0.0, sourcepattern=None, emittercoefficient=0.0, demandpattern=None, demand=50.0) 50.0 0.0
...

Adding Components

If you want to add a new component, you can use the utility functions provided in the adders module. Here, we create a new junction and a new pipe to the system:

on.add_junction(network=network, junction=on.Junction(id='J-32', xcoordinate=5500, ycoordinate=8000, demand=80))

on.add_pipe(network=network, pipe=on.Pipe(id='P-51', length=1000, diameter=400, roughness=0.26,
                                          startnode=on.get_node(network, 'J-32'), endnode=on.get_node(network, 'J-26')))
_images/adders_and_removers_2.png

Removing Components

Now, we want to remove the junction with the ID J-24 and all links connected to it. First, we get the junction object and use another utility function, get_adjacent_links(), to get a list of all links connected to the junction:

rjid = 'J-24'
rj = on.get_node(network, rjid)
neighbor_links = on.get_adjacent_links(network, rj)

Now, we can make use of the removing functions in the removers module. We first remove the links and then the junction from the model:

for neighbour in neighbor_links:
    on.remove_pipe(network=network, id=neighbour.id)

on.remove_junction(network=network, id=rjid)
_images/adders_and_removers_3.png

Summary

import os

import oopnet as on

blank_network = on.Network()

filename = os.path.join('data', 'Poulakis.inp')
network = on.Network.read(filename)

network.write('new_model.inp')

for j in on.get_junctions(network):
    print(j, j.demand, j.elevation)

on.add_junction(network=network, junction=on.Junction(id='J-32', xcoordinate=5500, ycoordinate=8000, demand=80))

on.add_pipe(network=network, pipe=on.Pipe(id='P-51', length=1000, diameter=400, roughness=0.26,
                                          startnode=on.get_node(network, 'J-32'), endnode=on.get_node(network, 'J-26')))

rjid = 'J-24'
rj = on.get_node(network, rjid)
neighbor_links = on.get_adjacent_links(network, rj)

for neighbour in neighbor_links:
    on.remove_pipe(network=network, id=neighbour.id)

on.remove_junction(network=network, id=rjid)