ReservoirManagement.jl is a Julia package that can be used to manage reservoirs (such as dams) using mathematical optimisation tools. Its design should allow easy extensibility for new use cases and kinds of management. For now, it focuses on determining rule curves, based on inflow to the reservoir and purpose needs.
This package relies on mathematical optimisation, and thus requires a solver to be installed. For most features, a simple LP solver is enough (in rare cases, a MIP solver is required). Any solver that implements the MathProgBase interface works (see JuliaOpt's website for more information).
Caution: For now, Gurobi is hardcoded into the source code, occurrences of
GurobiSolver() must be replaced by the corresponding solver object. This will be addressed in a near release.
For some statistical operations, this package uses unpublished Julia packages, which thus need to be installed separately (namely, ExtremeValueDistributions.jl for fitting extreme value distributions). Execute those commands from a Julia shell:
Pkg.clone("https://github.com/sammorris81/MetropolisUpdaters.jl.git") Pkg.clone("https://github.com/sammorris81/DataTransformations.jl.git") Pkg.clone("https://github.com/sammorris81/ExtremeValueDistributions.jl.git") Pkg.add("Optim") Pkg.checkout("ExtremeValueDistributions", "develop")
using ReservoirManagement using SIUnits using SIUnits.ShortUnits
The first step is to define the topology of the reservoir: the tributaries. This package defines two kinds of rivers: those that directly flow into the reservoir (the most common case), represented by
NaturalRiver, and diverted rivers (whose contribution can be decided up to some level),
The main information stored for each river is a series of inflow scenarios, each scenario being represented by an array of time series (whose type is
For example, the Vesdre reservoir has two main tributaries (the rivers Vesdre and Getzbach), plus one diverted river (Helle, which has a minimum environmental flow that must remain in the river after the diversion):
Vesdre = NaturalRiver(name="Vesdre", scenarios=scenariosVesdre) Getzbach = NaturalRiver(name="Getzbach", scenarios=scenariosGetzbach) Helle = DivertedRiver(name="Vesdre", scenarios=scenariosHelle, environmental_flow=0.5m^3/s, maximum_flow=15.0m^3/s)
Once this topology is modelled, a reservoir can be defined. The main parameters are:
purpose = DeterministicPurposes(drinkingWater=0.5m^3/s) out = ConstantDamOutputs(bottomOutlets=100m^3/s) VesdreReservoir = Reservoir(name="Vesdre", capacity=(2500000.m^3, 25000000.m^3), purposes=purpose, outputs=out, rivers_in=[Vesdre, Getzbach], rivers_diverted=[Helle])
The setup phase is done: with this
Reservoir data structure, this package can provide optimisation results with the
report() function. For now, it focuses on the determination of minimum rule curves (that span over
ruleDuration) that guarantee the purposes for some duration (
guarantee). If provided, it can compare its results to the current rule curve (
currentRuleCurve). The results are mainly a series of plots (enabled by
savePlots=true and saved into
saveFolder), but also the intermediate results (enabled by
saveIntermediate=true and also saved into
report(VesdreReservoir, ruleDuration=Year(1), guarantee=Year(2), currentRuleCurve=current_target, saveFolder="…/outputs/", savePlots=true, saveIntermediate=true)
Remark: The values in this example are not the true ones (albeit they are realistic).
6 months ago