Reservoirs store water between timesteps. They are nodes in the water network, and receive upstream flows and precipitation, and provide withdrawals to canals. However, their outflows are determined by an optimization.
In [1]:
include("../src/lib/readconfig.jl")
include("../src/lib/reservoirs.jl")
config = readconfig("../configs/standard.yml")
Out[1]:
In [2]:
@doc getreservoirs
Out[2]:
In [3]:
getreservoirs(config)
Out[3]:
To understand the functioning of reservoirs, consider how they work in a very simple three gauge example. The three guages example has three counties, with a river running through them. The middle county has a reservoir. Water is supplied only upstream (in counties 1 and 2) and consumed only downstream (in counties 2 and 3).
Note that the reservoir appears to be outside of the river system. While it is spatially synonymous with the middle gauge, reservoirs get all of their inflows from "captured" water. Any water that is not captured is allowed to run through the reservoir just like a stream. Reservoir captures can also be negative, providing releases.
The optimize-surface.jl
script models the constraints to satisfy surface water demands, using reservoirs to store water between periods.
In the three counties example, the first period has more rainfall than the second period, so that storage is optimal.
In [25]:
config = readconfig("../configs/dummy3.yml")
include("../src/optimize-surface.jl")
Out[25]:
First, look at the runoff values, with rows for the three gauges and columns for the two time periods.
In [26]:
runoff
Out[26]:
The requirements are for one unit of water each period for each of the lower two gauges.
In [28]:
reshape(constraintoffset_allocation_recordedbalance(m).f, 3, 3)
Out[28]:
The order of the parameters in the LP problem is:
In [29]:
parameters
Out[29]:
And the order of the constraint variables is:
In [30]:
constraints
Out[30]:
Consider the constraint matrix one parameter at a time. The first parameter is the water drawn from the supersource, which only affects the second constraint, :balance
, the difference between water demand and water supply. The objective function is such that supersource withdrawals are avoided.
In [33]:
full(house.A)[:, 1:9]
Out[33]:
Normal withdrawals affect :balance
as well, but they also affect the level of streamflow, which is constrained to be above 0. See the top six rows in two blocks, in the upper left and lower right, corresponding to the two periods. The gauges are ordered, by chance, such that the most upstream gauge is second, so a withdrawal from that gauge causes all three gauges to inch closer to empty.
In [34]:
full(house.A)[:, 10:18]
Out[34]:
We'll ignore the :returns
constraint. The last is the reservoir in the two periods. Reservoir captures have the same affect on streamflows, at least downstream. They have no direct effect on :balance
. Finally, they affect the last two constraints on the upper and lower bounds of the reservoir, where capture (or release) in period 1 affects both periods, while capture (or release) in period 2 only affects one.
In [35]:
full(house.A)[:, end-1:end]
Out[35]:
The result is that it is optimal to store one unit of water and release it in the second period.
In [36]:
constraining(house, sol.sol)
Out[36]:
Future work:
Received Maximum capacity for 2641 reservoirs from the US Army Corps of Engineers. However, in the allreservoirs.csv file in the folder awash/data/reservoirs/,there are 2671 reservoirs in total.
The allreservoir.csv database is being used in the reservoir optimization (reservoir.jl). The remaining 30 reservoirs are from the USGS website.
Since we are unable to currently find the maximum capacity for those 30 reservoirs (reservoir codes mentioned below), for this example, the maximum capacity is taken as 0.
usgsres 3170500 usgsres 5113750 usgsres 6886900 usgsres 7233550 usgsres 7332610 usgsres 7342495 usgsres 7343460 usgsres 7344488 usgsres 8025350 usgsres 8051100 usgsres 8064550 usgsres 8072500 usgsres 8073000 usgsres 8079700 usgsres 8092500 usgsres 8095550 usgsres 8118000 usgsres 8123000 usgsres 8123755 usgsres 8123950 usgsres 8131200 usgsres 8134500 usgsres 8136600 usgsres 8180010 usgsres 8202800 usgsres 9125800 usgsres 9129550 usgsres 9143600 usgsres 9147022 usgsres 15225990
The minimum reservoir storage is assumed to be 10% of the maximum reservoir storage, i.e.
storagecapacitymin = 0.1 * storagecapacitymax
This data needs improvement -- we need to find the minimum storage for each reservoir rather than taking one assumptions for all reservoirs
The initial storage is assumed to be the average of minimum and maximum capacity, i.e.
Initial storage = (storagecapacitymax-storagecapacitymin)/2
This data needs improvement -- we need to find the initial storage of each reservoir
Evaporation is currently assumed to be 1% of the storage capacity, i.e.
Evaporation = 0.01 * storagecapacitymax
The data needs improvement -- we need to find a linear relationship between evaporation and reservoir storage.
In [ ]: