Reservoir schedule

Reservoir schedule#

Reservoir schedule can be used to impose a specific strategy instead of using water values, but will also strictly limit how the system can be operated. Therefore, it should be used very carefully. Reservoir schedule has a significant different behaviour from other schedules. It has to be activated using the schedule_flag where the flag value 1 is used to impose a schedule at the end of the optimisation horizon, while 2 is used to impose a schedule within the optimization period. Also note that for ASCII input, the value must be repeated for each step where the schedule should be valid.

The example below shows how the end volume is scheduled to 3 by setting schedule_flag 1:

from pyshop import ShopSession
from basic import build_model
import pandas as pd
import numpy as np
import plotly.graph_objs as go


shop = ShopSession()
build_model(shop)
starttime = shop.get_time_resolution()['starttime']

discharge_river = shop.model.river.add_object('DischargeRiver')
discharge_river.upstream_elevation.set(43)
discharge_river.downstream_elevation.set(0)
discharge_river.width_depth_curve.set(pd.Series(index=[10, 10], data=[0, 7]))
shop.model.reservoir.Reservoir2.connect_to(discharge_river)

shop.model.reservoir.Reservoir1.start_vol.set(6)
shop.model.reservoir.Reservoir1.schedule.set(
    pd.Series(
        index=[starttime + pd.Timedelta(hours=t) for t in range(0,24,6)],
        data=[6, 5, 4, 3]
    )
)
shop.model.reservoir.Reservoir1.schedule_flag.set(1)
shop.model.reservoir.Reservoir1.inflow.set(30)

shop.start_sim([], [3])
reservoir_volume = shop.model.reservoir.Reservoir1.storage.get()

fig = go.Figure()
fig.add_trace(go.Scatter(x=reservoir_volume.index, y=reservoir_volume.values, name="Reservoir storage"))
fig.update_layout(xaxis_title="Time", yaxis_title="Volume")

fig.show()

The next example shows how volumes are scheduled by setting schedule_flag 2 for hour 6 and 13:

shop = ShopSession()
build_model(shop)
starttime = shop.get_time_resolution()['starttime']

discharge_river = shop.model.river.add_object('DischargeRiver')
discharge_river.upstream_elevation.set(43)
discharge_river.downstream_elevation.set(0)
discharge_river.width_depth_curve.set(pd.Series(index=[10, 10], data=[0, 7]))
shop.model.reservoir.Reservoir2.connect_to(discharge_river)

shop.model.reservoir.Reservoir1.start_vol.set(6)
shop.model.reservoir.Reservoir1.schedule.set(
    pd.Series(
        index=[starttime + pd.Timedelta(hours=t) for t in range(0,24,6)],
        data=[6, 5, 4, 3]
    )
)
shop.model.reservoir.Reservoir1.schedule_flag.set(
    pd.Series(
        index=[starttime, starttime + pd.Timedelta(hours=6), starttime + pd.Timedelta(hours=7), starttime + pd.Timedelta(hours=13), starttime + pd.Timedelta(hours=14)],
        data=[0, 2, 0, 2, 0]
    )
)
shop.model.reservoir.Reservoir1.inflow.set(30)

shop.start_sim([], [3])
reservoir_volume = shop.model.reservoir.Reservoir1.storage.get()

fig = go.Figure()
fig.add_trace(go.Scatter(x=reservoir_volume.index, y=reservoir_volume.values, name="Reservoir storage"))
fig.update_layout(xaxis_title="Time", yaxis_title="Volume")

fig.show()

The final example shows how slack can be used to expand the permitted end schedule value. The upper- and lower slack are 3.3 and 2.7 respectively. In the case, the water value is higher than the price hence the reservoir end volume is bounded by the upper slack value:

shop = ShopSession()
build_model(shop)
starttime = shop.get_time_resolution()['starttime']

discharge_river = shop.model.river.add_object('DischargeRiver')
discharge_river.upstream_elevation.set(43)
discharge_river.downstream_elevation.set(0)
discharge_river.width_depth_curve.set(pd.Series(index=[10, 10], data=[0, 7]))
shop.model.reservoir.Reservoir2.connect_to(discharge_river)

shop.model.reservoir.Reservoir1.start_vol.set(6)
shop.model.reservoir.Reservoir1.schedule.set(
    pd.Series(
        index=[starttime + pd.Timedelta(hours=t) for t in range(0,24,6)],
        data=[6, 5, 4, 3]
    )
)
shop.model.reservoir.Reservoir1.schedule_flag.set(1)
shop.model.reservoir.Reservoir1.upper_slack.set(3.3)
shop.model.reservoir.Reservoir1.lower_slack.set(2.7)
shop.model.reservoir.Reservoir1.inflow.set(30)

shop.start_sim([], [3])
reservoir_volume = shop.model.reservoir.Reservoir1.storage.get()

fig = go.Figure()
fig.add_trace(go.Scatter(x=reservoir_volume.index, y=reservoir_volume.values, name="Reservoir storage"))
fig.update_layout(xaxis_title="Time", yaxis_title="Volume")

fig.show()