Operation Problem with HydroPowerSimulations.jl

Note

HydroPowerSimulations.jl is an extension library of PowerSimulations.jl for modeling hydro units. Users are encouraged to review the single-step tutorial in PowerSimulations.jl before this tutorial.

Load packages

julia> using PowerSystems
julia> using PowerSimulations
julia> using HydroPowerSimulations
julia> using PowerSystemCaseBuilder
julia> using HiGHS # solver

Data

Note

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 build_system. For more details visit PowerSystemCaseBuilder README

julia> sys = build_system(PSITestSystems, "c_sys5_hy")┌ Info: Building new system c_sys5_hy from raw data
  sys_descriptor.raw_data = "/home/runner/.julia/artifacts/45fbc4fe058ae508e0d03c697ca276c3484a9c5e/PowerSystemsTestData-3.2/psy_data/data_5bus_pu.jl"
[ Info: Serialized time series data to /home/runner/.julia/packages/PowerSystemCaseBuilder/dJGb8/data/serialized_system/614e094ea985a55912fc1321256a49b755f9fc451c0f264f24d6d04af20e84d7/c_sys5_hy_time_series_storage.h5.
[ Info: Serialized System to /home/runner/.julia/packages/PowerSystemCaseBuilder/dJGb8/data/serialized_system/614e094ea985a55912fc1321256a49b755f9fc451c0f264f24d6d04af20e84d7/c_sys5_hy.json
[ Info: Serialized System metadata to /home/runner/.julia/packages/PowerSystemCaseBuilder/dJGb8/data/serialized_system/614e094ea985a55912fc1321256a49b755f9fc451c0f264f24d6d04af20e84d7/c_sys5_hy_metadata.json
System
┌───────────────────┬─────────────┐
│ Property          │ Value       │
├───────────────────┼─────────────┤
│ Name              │             │
│ Description       │             │
│ System Units Base │ SYSTEM_BASE │
│ Base Power        │ 100.0       │
│ Base Frequency    │ 60.0        │
│ Num Components    │ 26          │
└───────────────────┴─────────────┘

Static Components
┌─────────────────┬───────┐
│ Type            │ Count │
├─────────────────┼───────┤
│ ACBus           │ 5     │
│ Arc             │ 6     │
│ HydroDispatch   │ 1     │
│ Line            │ 6     │
│ PowerLoad       │ 3     │
│ ThermalStandard │ 5     │
└─────────────────┴───────┘

Forecast Summary
┌───────────────┬────────────────┬──────────────────┬─────────────────────┬─────
│ owner_type    │ owner_category │ time_series_type │ initial_timestamp   │ re ⋯
│ String        │ String         │ String           │ String              │ Da ⋯
├───────────────┼────────────────┼──────────────────┼─────────────────────┼─────
│ HydroDispatch │ Component      │ Deterministic    │ 2024-01-01T00:00:00 │ 1  ⋯
│ PowerLoad     │ Component      │ Deterministic    │ 2024-01-01T00:00:00 │ 1  ⋯
└───────────────┴────────────────┴──────────────────┴─────────────────────┴─────
                                                               5 columns omitted

With a single PowerSystems.HydroDispatch:

julia> hy = only(get_components(HydroDispatch, sys))HydroDispatch: HydroDispatch:
   name: HydroDispatch
   available: true
   bus: ACBus: nodeB
   active_power: 0.0
   reactive_power: 0.0
   rating: 6.0
   prime_mover_type: PowerSystems.PrimeMoversModule.PrimeMovers.HY = 16
   active_power_limits: (min = 0.0, max = 6.0)
   reactive_power_limits: (min = 0.0, max = 6.0)
   ramp_limits: nothing
   time_limits: nothing
   base_power: 100.0
   operation_cost: PowerSystems.HydroGenerationCost composed of variable: InfrastructureSystems.CostCurve{InfrastructureSystems.LinearCurve}
   services: 0-element Vector{PowerSystems.Service}
   dynamic_injector: nothing
   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: true

Decision Model

Setting up the formulations based on PowerSimulations.jl:

julia> template = ProblemTemplate(PTDFPowerModel)Network Model
┌───────────────┬─────────────────────────────────┐
│ Network Model │ PowerSimulations.PTDFPowerModel │
│ Slacks        │ false                           │
│ PTDF          │ false                           │
│ Duals         │ None                            │
└───────────────┴─────────────────────────────────┘

Device Models
┌─────────────┬─────────────┬────────┐
│ Device Type │ Formulation │ Slacks │
└─────────────┴─────────────┴────────┘
julia> set_device_model!(template, ThermalStandard, ThermalBasicDispatch)
julia> set_device_model!(template, PowerLoad, StaticPowerLoad)
julia> set_device_model!(template, Line, StaticBranch)

but, now we also include the hydro using HydroDispatchRunOfRiver:

julia> set_device_model!(template, HydroDispatch, HydroDispatchRunOfRiver)

With the template properly set-up, we construct, build and solve the optimization problem:

julia> model = DecisionModel(template, sys; optimizer = HiGHS.Optimizer)[ Info: Overriding time_series_cache_size because time series is stored in memory
Network Model
┌───────────────┬─────────────────────────────────┐
│ Network Model │ PowerSimulations.PTDFPowerModel │
│ Slacks        │ false                           │
│ PTDF          │ false                           │
│ Duals         │ None                            │
└───────────────┴─────────────────────────────────┘

Device Models
┌──────────────────────────────┬───────────────────────────────────────┬────────
│ Device Type                  │ Formulation                           │ Slack ⋯
├──────────────────────────────┼───────────────────────────────────────┼────────
│ PowerSystems.ThermalStandard │ PowerSimulations.ThermalBasicDispatch │ false ⋯
│ PowerSystems.PowerLoad       │ PowerSimulations.StaticPowerLoad      │ false ⋯
│ PowerSystems.HydroDispatch   │ HydroDispatchRunOfRiver               │ false ⋯
└──────────────────────────────┴───────────────────────────────────────┴────────
                                                                1 column omitted

Branch Models
┌───────────────────┬───────────────────────────────┬────────┐
│ Branch Type       │ Formulation                   │ Slacks │
├───────────────────┼───────────────────────────────┼────────┤
│ PowerSystems.Line │ PowerSimulations.StaticBranch │ false  │
└───────────────────┴───────────────────────────────┴────────┘
julia> build!(model; output_dir = mktempdir())InfrastructureSystems.Optimization.ModelBuildStatusModule.ModelBuildStatus.BUILT = 0
julia> solve!(model)InfrastructureSystems.Simulation.RunStatusModule.RunStatus.SUCCESSFULLY_FINALIZED = 0

Exploring Results

Results can be explored using:

julia> res = OptimizationProblemResults(model)Start: 2024-01-01T00:00:00
End: 2024-01-01T23:00:00
Resolution: 60 minutes

PowerSimulations Problem Auxiliary variables Results
┌──────────────────────────────────┐
│ HydroEnergyOutput__HydroDispatch │
└──────────────────────────────────┘

PowerSimulations Problem Expressions Results
┌───────────────────────────────────────────┐
│ ProductionCostExpression__HydroDispatch   │
│ ProductionCostExpression__ThermalStandard │
│ ActivePowerBalance__ACBus                 │
│ ActivePowerBalance__System                │
└───────────────────────────────────────────┘

PowerSimulations Problem Parameters Results
┌───────────────────────────────────────────────┐
│ ActivePowerTimeSeriesParameter__PowerLoad     │
│ ActivePowerTimeSeriesParameter__HydroDispatch │
└───────────────────────────────────────────────┘

PowerSimulations Problem Variables Results
┌──────────────────────────────────────┐
│ ActivePowerVariable__HydroDispatch   │
│ FlowActivePowerVariable__Line        │
│ ActivePowerVariable__ThermalStandard │
└──────────────────────────────────────┘

Use read_variable to read in the dispatch variable results for the hydro:

julia> var = read_variable(res, "ActivePowerVariable__HydroDispatch")24×2 DataFrame
 Row │ DateTime             HydroDispatch
     │ DateTime             Float64
─────┼────────────────────────────────────
   1 │ 2024-01-01T00:00:00       188.58
   2 │ 2024-01-01T01:00:00       232.01
   3 │ 2024-01-01T02:00:00       137.149
   4 │ 2024-01-01T03:00:00       136.006
   5 │ 2024-01-01T04:00:00       133.72
   6 │ 2024-01-01T05:00:00        77.718
   7 │ 2024-01-01T06:00:00        86.8608
   8 │ 2024-01-01T07:00:00       219.439
  ⋮  │          ⋮                 ⋮
  18 │ 2024-01-01T17:00:00       269.726
  19 │ 2024-01-01T18:00:00       378.303
  20 │ 2024-01-01T19:00:00       438.877
  21 │ 2024-01-01T20:00:00       466.307
  22 │ 2024-01-01T21:00:00       427.448
  23 │ 2024-01-01T22:00:00       468.593
  24 │ 2024-01-01T23:00:00       114.291
                            9 rows omitted