{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Custom Control Example" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import display, HTML\n", "display(HTML('\"Open'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[EPyT-Flow](https://github.com/WaterFutures/EPyT-Flow) is available on [PyPI](https://pypi.org/project/epyt-flow/) and can be installed via `pip install epyt-flow`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install epyt-flow --quiet" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from epyt_flow.data.networks import load_net1\n", "from epyt_flow.simulation import ScenarioSimulator\n", "from epyt_flow.simulation import CustomControlModule, ScadaData\n", "from epyt_flow.utils import to_seconds, volume_to_level\n", "from epyt_flow.simulation.events import ActuatorConstants" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A custom control module mimicing the control rules stated in Net1.inp -- note that all control modules must be derived from the [CustomControlModule](https://epyt-flow.readthedocs.io/en/stable/epyt_flow.simulation.scada.html#epyt_flow.simulation.scada.custom_control.CustomControlModule) class:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class MyControl(CustomControlModule):\n", " def __init__(self, **kwds):\n", " # Tank and pump ID\n", " self.__tank_id = \"2\"\n", " self.__pump_id = \"9\"\n", "\n", " # Tank diameter could be also obtained from EPANET\n", " self.__tank_diameter = 50.5\n", "\n", " # Lower and upper threshold on tank level\n", " self.__lower_level_threshold = 110\n", " self.__upper_level_threshold = 140\n", "\n", " super().__init__(**kwds)\n", "\n", " def step(self, scada_data: ScadaData) -> None:\n", " # Retrieve current water level in the tank\n", " tank_volume = scada_data.get_data_tanks_water_volume([self.__tank_id])[0, 0]\n", " tank_level = volume_to_level(float(tank_volume), self.__tank_diameter)\n", "\n", " # Decide if pump has to be deactivated or re-activated\n", " if tank_level <= self.__lower_level_threshold:\n", " self.set_pump_status(self.__pump_id, ActuatorConstants.EN_OPEN)\n", " elif tank_level >= self.__upper_level_threshold:\n", " self.set_pump_status(self.__pump_id, ActuatorConstants.EN_CLOSED)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create new simulation based on Net1:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim = ScenarioSimulator(scenario_config=load_net1(verbose=False))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set simulation duration to two days:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.set_general_parameters(simulation_duration=to_seconds(days=2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Monitor states of tank \"2\" and pump \"9\":" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.set_tank_sensors(sensor_locations=[\"2\"])\n", "sim.set_pump_state_sensors(sensor_locations=[\"9\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that Net1.inp contains some simple controls. Remove all of them by calling [remove_all_simple_controls()](https://epyt-flow.readthedocs.io/en/stable/epyt_flow.simulation.html#epyt_flow.simulation.scenario_simulator.ScenarioSimulator.remove_all_simple_controls):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.remove_all_simple_controls()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add our custom control module by calling [add_custom_control()](https://epyt-flow.readthedocs.io/en/stable/epyt_flow.simulation.html#epyt_flow.simulation.scenario_simulator.ScenarioSimulator.add_custom_control):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.add_custom_control(MyControl())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run the simulation and show sensor readings over time:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scada_data = sim.run_simulation()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scada_data.plot_pumps_state()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scada_data.plot_tanks_water_volume()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do not forget to close the simulation!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.close()" ] } ], "metadata": { "kernelspec": { "display_name": "epytflow2", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.20" } }, "nbformat": 4, "nbformat_minor": 2 }