HydroWaterFactorModel model tutorial
To follow along, you can download this tutorial as a Julia script (.jl) or Jupyter notebook (.ipynb).
HydroPowerSimulations.jl is an extension library of PowerSimulations.jl for modeling hydro units. Users are encouraged to review the tutorial in PowerSimulations.jl on Running a Single-Step Problem before this tutorial.
Load packages
using PowerSystems
using PowerSimulations
using HydroPowerSimulations
using PowerSystemCaseBuilder
using Ipopt ## solverData
PowerSystemCaseBuilder.jl is a helper library that makes it easier to reproduce examples in the documentation and tutorials. Normally you would pass your local files to create the system data instead of calling the function PowerSystemCaseBuilder.build_system.
sys = build_system(PSITestSystems, "c_sys5_hy_turbine_energy")| System | |
| Property | Value |
|---|---|
| Name | |
| Description | |
| System Units Base | SYSTEM_BASE |
| Base Power | 100.0 |
| Base Frequency | 60.0 |
| Num Components | 27 |
| Static Components | |
| Type | Count |
|---|---|
| ACBus | 5 |
| Arc | 6 |
| HydroReservoir | 1 |
| HydroTurbine | 1 |
| Line | 6 |
| PowerLoad | 3 |
| ThermalStandard | 5 |
| Forecast Summary | |||||||||
| owner_type | owner_category | name | time_series_type | initial_timestamp | resolution | count | horizon | interval | window_count |
|---|---|---|---|---|---|---|---|---|---|
| String | String | String | String | String | Dates.CompoundPeriod | Int64 | Dates.CompoundPeriod | Dates.CompoundPeriod | Int64 |
| HydroReservoir | Component | hydro_budget | Deterministic | 2024-01-01T00:00:00 | 1 hour | 1 | 1 day | 1 day | 2 |
| HydroReservoir | Component | inflow | Deterministic | 2024-01-01T00:00:00 | 1 hour | 1 | 1 day | 1 day | 2 |
| HydroReservoir | Component | storage_target | Deterministic | 2024-01-01T00:00:00 | 1 hour | 1 | 1 day | 1 day | 2 |
| HydroTurbine | Component | max_active_power | Deterministic | 2024-01-01T00:00:00 | 1 hour | 1 | 1 day | 1 day | 2 |
| PowerLoad | Component | max_active_power | Deterministic | 2024-01-01T00:00:00 | 1 hour | 3 | 1 day | 1 day | 2 |
With a single PowerSystems.HydroTurbine connected downstream to a PowerSystems.HydroReservoir:
reservoir = only(get_components(HydroReservoir, sys))HydroReservoir: HydroEnergyReservoir__reservoir:
name: HydroEnergyReservoir__reservoir
available: true
storage_level_limits: (min = 0.0, max = 5000.0)
initial_level: 0.5
spillage_limits: nothing
inflow: 4.0
outflow: 0.0
level_targets: 1.0
intake_elevation: 0.0
head_to_volume_factor: InfrastructureSystems.LinearCurve(0.0, 0.0)
upstream_turbines: 0-element Vector{PowerSystems.HydroUnit}
downstream_turbines: 1-element Vector{PowerSystems.HydroUnit}
upstream_reservoirs: 0-element Vector{PowerSystems.Device}
operation_cost:
level_data_type: PowerSystems.ReservoirDataTypeModule.ReservoirDataType.ENERGY = 4
ext: Dict{String, Any}()
InfrastructureSystems.SystemUnitsSettings:
base_value: 100.0
unit_system: InfrastructureSystems.UnitSystemModule.UnitSystem.SYSTEM_BASE = 0
has_supplemental_attributes: false
has_time_series: trueSet the storage level limits using set_storage_level_limits!. Here the limits are set between $4000 and 6000 m^3$ .
set_storage_level_limits!(reservoir, (min = 4000, max = 6000))(min = 4000, max = 6000)Set the lower bound of reservoir volume using set_level_targets!. Here the level target is set at $0.9 \cdot 6000 = 5400 m^3$.
set_level_targets!(reservoir, 0.9)0.9Set the headtovolume factor to 1.0 using set_head_to_volume_factor!, since is an energy model and no conversion is needed.
set_head_to_volume_factor!(reservoir, LinearCurve(1.0))InfrastructureSystems.LinearCurve (a type of InfrastructureSystems.InputOutputCurve) where function is: f(x) = 1.0 x + 0.0Decision Model
Setting up the formulations based on PowerSimulations.jl:
template = ProblemTemplate(CopperPlatePowerModel)
set_device_model!(template, ThermalStandard, ThermalBasicDispatch)
set_device_model!(template, PowerLoad, StaticPowerLoad)but, now we also include the HydroReservoir and HydroTurbine using HydroWaterFactorModel:
set_device_model!(template, HydroReservoir, HydroWaterFactorModel)
set_device_model!(template, HydroTurbine, HydroWaterFactorModel)With the template properly set-up, we construct, build and solve the optimization problem:
model = DecisionModel(template, sys; optimizer = Ipopt.Optimizer)
build!(model; output_dir = mktempdir())
solve!(model)InfrastructureSystems.Simulation.RunStatusModule.RunStatus.SUCCESSFULLY_FINALIZED = 0Exploring Results
Results can be explored using:
results = OptimizationProblemResults(model)Start: 2024-01-01T00:00:00
End: 2024-01-01T23:00:00
Resolution: 60 minutes
| PowerSimulations Problem Auxiliary variables Results |
| HydroEnergyOutput__HydroTurbine |
| PowerSimulations Problem Expressions Results |
| ActivePowerBalance__System |
| ProductionCostExpression__ThermalStandard |
| ProductionCostExpression__HydroTurbine |
| PowerSimulations Problem Parameters Results |
| InflowTimeSeriesParameter__HydroReservoir |
| ActivePowerTimeSeriesParameter__PowerLoad |
| PowerSimulations Problem Variables Results |
| ActivePowerVariable__ThermalStandard |
| ActivePowerVariable__HydroTurbine |
| WaterSpillageVariable__HydroReservoir |
| HydroReservoirVolumeVariable__HydroReservoir |
Use read_variable to read in the dispatch variable results for the hydro:
power =
read_variable(
results,
"ActivePowerVariable__HydroTurbine";
table_format = TableFormat.WIDE,
)| DateTime | HydroEnergyReservoir_turbine |
|---|---|
| Dates.DateTime | Float64? |
| 2024-01-01T00:00:00 | 700.0000069796481 |
| 2024-01-01T01:00:00 | 692.1153451399834 |
| 2024-01-01T02:00:00 | 670.2280854399376 |
| 2024-01-01T03:00:00 | 643.44897543993 |
| 2024-01-01T04:00:00 | 649.1417270399309 |
| 2024-01-01T05:00:00 | 658.8662063399331 |
| 2024-01-01T06:00:00 | 688.0143081399618 |
| 2024-01-01T07:00:00 | 700.0000069796547 |
| 2024-01-01T08:00:00 | 700.0000069796495 |
| 2024-01-01T09:00:00 | 700.0000069796482 |
| ⋮ | ⋮ |
or the volume level of the reservoir
volume =
read_variable(
results,
"HydroReservoirVolumeVariable__HydroReservoir";
table_format = TableFormat.WIDE,
)| DateTime | HydroEnergyReservoir__reservoir |
|---|---|
| Dates.DateTime | Float64? |
| 2024-01-01T00:00:00 | 4238.884628529651 |
| 2024-01-01T01:00:00 | 4942.327912266409 |
| 2024-01-01T02:00:00 | 4902.509727587584 |
| 2024-01-01T03:00:00 | 4906.116732850918 |
| 2024-01-01T04:00:00 | 4991.314427862555 |
| 2024-01-01T05:00:00 | 4876.110710237051 |
| 2024-01-01T06:00:00 | 4777.738351930663 |
| 2024-01-01T07:00:00 | 4958.217986682351 |
| 2024-01-01T08:00:00 | 4802.637219269302 |
| 2024-01-01T09:00:00 | 4894.1386504587435 |
| ⋮ | ⋮ |
Note that the final reservoir level is between the set level target and the maximum storage level.