Overflow modelling
This example will demonstrate overflow modelling based on the basic example. The recommended method of modelling overflow is using the river object. The river upstream_elevation should be equal to the reservoir hrl. The river may also use a flow description, such as up_level_flow_curve or width_depth_curve to describe the level-dependent flow. Additionally, flow_cost can be used to penalize overflow.
The model setup is available in the following formats:
pyshop
The example below illustrates overflow modelling in SHOP:
from pyshop import ShopSession
from basic import build_model
import pandas as pd
import plotly.graph_objs as go
shop = ShopSession()
build_model(shop)
starttime = shop.get_time_resolution()['starttime']
# Add spill river and set elevation to hrl
spill_river = shop.model.river.add_object('SpillRiver')
spill_river.upstream_elevation.set(100)
spill_river.downstream_elevation.set(90)
# Connect objects in watercourse
shop.model.reservoir.Reservoir1.connect_to(spill_river)
spill_river.connect_to(shop.model.reservoir.Reservoir2)
# Add river to describe flow out of reservoir below. (Crest at 43 meters.)
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)
# Set start level to almost full, high inflow and scheduled production to ensure overflow
shop.model.reservoir.Reservoir1.start_level.set(98)
shop.model.reservoir.Reservoir1.inflow.set(200)
shop.model.generator.P1G1.production_schedule.set(50)
shop.start_sim([], [3])
spill_flow = spill_river.flow.get()
fig = go.Figure()
fig.add_trace(go.Scatter(x=spill_flow.index, y=spill_flow.values, name="Spill gate flow"))
fig.update_layout(xaxis_title="Time", yaxis_title="Flow")
fig.show()In the illustrated case, all water above the maximum volume is routed to the spill gate immediately. Alternatively, a flow function can be used as shown below where the overflow is given by a width_depth_curve:
shop = ShopSession()
build_model(shop)
starttime = shop.get_time_resolution()['starttime']
# Add spill river and set elevation to hrl
spill_river = shop.model.river.add_object('SpillRiver')
spill_river.upstream_elevation.set(100)
spill_river.downstream_elevation.set(90)
# Use widht depth curve for overflow description
spill_river.width_depth_curve.set(pd.Series(index=[30, 30], data=[0, 1]))
# Connect objects in watercourse
shop.model.reservoir.Reservoir1.connect_to(spill_river)
spill_river.connect_to(shop.model.reservoir.Reservoir2)
# Add river to describe flow out of reservoir below. (Crest at 43 meters.)
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)
# Set start level to almost full, high inflow and scheduled production to ensure overflow
shop.model.reservoir.Reservoir1.start_level.set(98)
shop.model.reservoir.Reservoir1.inflow.set(200)
shop.model.generator.P1G1.production_schedule.set(50)
shop.start_sim([], [3])
spill_flow = spill_river.flow.get()
fig = go.Figure()
fig.add_trace(go.Scatter(x=spill_flow.index, y=spill_flow.values, name="Spill gate flow"))
fig.update_layout(xaxis_title="Time", yaxis_title="Flow")
fig.show()Overflow with gate¶
Before river was introduced in SHOP, overflow was modelled using gate. This is still supported and requires that the relation between level and overflow is given by flow_descr. Moreover, the upstream reservoir and the spill gate must be connected using the spill connection type. The example below show how the overflow can be modelled using a spill gate.
shop = ShopSession()
build_model(shop)
starttime = shop.get_time_resolution()['starttime']
# Add spill gate and set flow_descr
spill_gate = shop.model.gate.add_object('SpillGate')
shop.model.reservoir.Reservoir1.flow_descr.set(pd.Series([0, 1000], index=[100, 101]))
# Connect objects in watercourse
shop.model.reservoir.Reservoir1.connect_to(spill_gate, 'spill')
spill_river.connect_to(shop.model.reservoir.Reservoir2)
# Add river to describe flow out of reservoir below. (Crest at 43 meters.)
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)
# Set start level to almost full, high inflow and scheduled production to ensure overflow
shop.model.reservoir.Reservoir1.start_level.set(98)
shop.model.reservoir.Reservoir1.inflow.set(200)
shop.model.generator.P1G1.production_schedule.set(50)
shop.start_sim([], [3])
spill_flow = spill_gate.discharge.get()
fig = go.Figure()
fig.add_trace(go.Scatter(x=spill_flow.index, y=spill_flow.values, name="Spill gate flow"))
fig.update_layout(xaxis_title="Time", yaxis_title="Flow")
fig.show()The history saving thread hit an unexpected error (OperationalError('database is locked')).History will not be written to the database.