Complex Control Example

[1]:
from IPython.display import display, HTML
display(HTML('<a target="_blank" href="https://colab.research.google.com/github/WaterFutures/EPyT-Flow/blob/main/docs/examples/control_example.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>'))
Open In Colab

EPyT-Flow is available on PyPI and can be installed via pip install epyt-flow:

[2]:
%pip install epyt-flow --quiet
Note: you may need to restart the kernel to use updated packages.
[3]:
from epyt_flow.data.networks import load_net1
from epyt_flow.simulation import ScenarioSimulator, EpanetConstants
from epyt_flow.simulation.scada import ComplexControlModule, RuleAction, RuleCondition, \
    EN_R_LEVEL, EN_R_LEQ, EN_R_GEQ, EN_R_ACTION_STATUS_CLOSED, EN_R_ACTION_STATUS_OPEN
from epyt_flow.utils import to_seconds

Create two complex control modules (i.e. entries in the “RULES” section of an .inp file) for controlling pump “9” based on the water leven in tank “2”:

  • IF TANK 2 LEVEL <= 110 THEN PUMP 9 SETTING IS OPEN

  • IF TANK 2 LEVEL >= 140 THEN PUMP 9 SETTING IS CLOSED

The first control rule: IF TANK 2 LEVEL <= 110 THEN PUMP 9 SETTING IS OPEN

  1. Create the condition (instance of RuleCondition) TANK 2 LEVEL <= 110

  2. Create the action (instance of RuleAction): PUMP 9 SETTING IS OPEN

  3. Combine condition and action into the final control rule (instance of ComplexControlModule)

[4]:
# IF TANK 2 LEVEL <= 110 THEN PUMP 9 SETTING IS OPEN
# Create the condition: TANK 2 LEVEL <= 110
condition_1 = RuleCondition(object_type_id=EpanetConstants.EN_R_NODE,
                            object_id="2",
                            attribute_id=EN_R_LEVEL,
                            relation_type_id=EN_R_LEQ,
                            value=110)

# Create the action: PUMP 9 SETTING IS OPEN
action_1 = RuleAction(link_type_id=EpanetConstants.EN_PUMP,
                      link_id="9",
                      action_type_id=EN_R_ACTION_STATUS_OPEN,
                      action_value=None)

# Combine condition and action into the final control rule
my_control_1 = ComplexControlModule(rule_id="PUMP-9_1",
                                    condition_1=condition_1,
                                    additional_conditions=[],
                                    actions=[action_1],
                                    else_actions=[],
                                    priority=1)

The second control rule: IF TANK 2 LEVEL >= 140 THEN PUMP 9 SETTING IS CLOSED

  1. Create the condition (instance of RuleCondition) TANK 2 LEVEL >= 140

  2. Create the action (instance of RuleAction): PUMP 9 SETTING IS CLOSED

  3. Combine condition and action into the final control rule (instance of ComplexControlModule)

[5]:
# IF TANK 2 LEVEL >= 140 THEN PUMP 9 SETTING IS CLOSED
# Create condition: TANK 2 LEVEL >= 140
condition_1 = RuleCondition(object_type_id=EpanetConstants.EN_R_NODE,
                            object_id="2",
                            attribute_id=EN_R_LEVEL,
                            relation_type_id=EN_R_GEQ,
                            value=140)

# Create action: TANK 2 LEVEL >= 140
action_1 = RuleAction(link_type_id=EpanetConstants.EN_PUMP,
                      link_id="9",
                      action_type_id=EN_R_ACTION_STATUS_CLOSED,
                      action_value=None)

# Combine condition and action into the final control rule
my_control_2 = ComplexControlModule(rule_id="PUMP-9_2",
                                    condition_1=condition_1,
                                    additional_conditions=[],
                                    actions=[action_1],
                                    else_actions=[],
                                    priority=1)

Create new simulation based on Net1:

[6]:
sim = ScenarioSimulator(scenario_config=load_net1(verbose=False))

Set simulation duration to two days:

[7]:
sim.set_general_parameters(simulation_duration=to_seconds(days=2))

Monitor states of tank “2” and pump “9”:

[8]:
sim.set_tank_sensors(sensor_locations=["2"])
sim.set_pump_state_sensors(sensor_locations=["9"])

Note that Net1.inp contains some simple controls. Remove all of them by calling remove_all_simple_controls():

[9]:
sim.remove_all_simple_controls()

Add our complex control modules by calling add_complex_control():

[10]:
sim.add_complex_control(my_control_1)
sim.add_complex_control(my_control_2)

Run the simulation and show sensor readings over time:

[11]:
scada_data = sim.run_simulation()
[12]:
scada_data.plot_pumps_state()
../_images/examples_complex_control_example_22_0.png
[12]:
<Axes: xlabel='Time (60min steps)', ylabel='Pump state'>
[13]:
scada_data.plot_tanks_water_volume()
../_images/examples_complex_control_example_23_0.png
[13]:
<Axes: xlabel='Time (60min steps)', ylabel='Water volume in $feet^3$'>

Do not forget to close the simulation!

[14]:
sim.close()