Originally Contributed by: Clayton Barrows
PowerSimulations.jl supports simulations that consist of sequential optimization problems where results from previous problems inform subsequent problems in a variety of ways. This example demonstrates some of these capabilities to represent electricity market clearing.
First, let's create System
s to represent the Day-Ahead and Real-Time market clearing
process with hourly, and 5-minute time series data, respectively.
using PowerSystems
using PowerSimulations
using PowerSystemCaseBuilder
using Dates
using DataFrames
using Cbc # mip solver
solver = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 1, "ratioGap" => 0.5)
using Ipopt # solver that supports duals
ipopt_solver = optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
MathOptInterface.OptimizerWithAttributes(Ipopt.Optimizer, Pair{MathOptInterface.AbstractOptimizerAttribute, Any}[MathOptInterface.RawParameter("print_level") => 0])
The five bus system data here includes hourly day-ahead data, 5-minute real-time market data, and 6-second actual data. We'll only use the hourly and 5-minute data for the example simulations below, but the 6-second data is included for future development.
sys_DA = build_system(SIIPExampleSystems, "5_bus_matpower_DA")
sys_RT = build_system(SIIPExampleSystems, "5_bus_matpower_RT")
┌ Info: Building new system 5_bus_matpower_DA from raw data └ sys_descriptor.raw_data = "/Users/cbarrows/.julia/packages/PowerSystemCaseBuilder/4FIfo/data/matpower/case5_re_uc.m" [ Info: extending matpower format with data: areas 1x3 [ Info: extending matpower format with data: gen_name 7x4 [ Info: extending matpower format by appending matrix "gen_name" in to "gen" [ Info: reversing the orientation of branch 6 (4, 3) to be consistent with other parallel branches [ Info: the voltage setpoint on generator 4 does not match the value at bus 4 [ Info: the voltage setpoint on generator 1 does not match the value at bus 1 [ Info: the voltage setpoint on generator 5 does not match the value at bus 10 [ Info: the voltage setpoint on generator 2 does not match the value at bus 1 [ Info: the voltage setpoint on generator 3 does not match the value at bus 3 [ Info: removing 1 cost terms from generator 4: [4000.0, 0.0] [ Info: removing 1 cost terms from generator 1: [1400.0, 0.0] [ Info: removing 1 cost terms from generator 5: [1000.0, 0.0] [ Info: removing 1 cost terms from generator 2: [1500.0, 0.0] [ Info: removing 3 cost terms from generator 6: Float64[] [ Info: removing 3 cost terms from generator 7: Float64[] [ Info: removing 1 cost terms from generator 3: [3000.0, 0.0] ┌ Info: Constructing System from Power Models │ data["name"] = "nesta_case5_pjm" └ data["source_type"] = "matpower" [ Info: Reading bus data [ Info: Reading generator data [ Info: Reading branch data ┌ Warning: Rate 1200.0 MW for bus2-bus3-i_4 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 ┌ Warning: Rate 200.0 MW for bus1-bus2-i_1 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 ┌ Warning: Rate 200.0 MW for bus1-bus4-i_2 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 ┌ Warning: Rate 200.0 MW for bus4-bus5-i_7 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 ┌ Warning: Rate 1000.0 MW for bus1-bus5-i_3 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 [ Info: Reading branch data [ Info: Reading DC Line data [ Info: Reading storage data ┌ Warning: no component category=Generator name=HydroDispatch1 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch2 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch3 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch1 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch2 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch3 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch1 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch3 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch1 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch3 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 [ Info: Serialized time series data to /Users/cbarrows/.julia/packages/PowerSystemCaseBuilder/4FIfo/data/serialized_system/ForecastOnly/5_bus_matpower_DA_time_series_storage.h5. [ Info: Serialized System to /Users/cbarrows/.julia/packages/PowerSystemCaseBuilder/4FIfo/data/serialized_system/ForecastOnly/5_bus_matpower_DA.json ┌ Info: Building new system 5_bus_matpower_RT from raw data └ sys_descriptor.raw_data = "/Users/cbarrows/.julia/packages/PowerSystemCaseBuilder/4FIfo/data/matpower/case5_re_uc.m" [ Info: extending matpower format with data: areas 1x3 [ Info: extending matpower format with data: gen_name 7x4 [ Info: extending matpower format by appending matrix "gen_name" in to "gen" [ Info: reversing the orientation of branch 6 (4, 3) to be consistent with other parallel branches [ Info: the voltage setpoint on generator 4 does not match the value at bus 4 [ Info: the voltage setpoint on generator 1 does not match the value at bus 1 [ Info: the voltage setpoint on generator 5 does not match the value at bus 10 [ Info: the voltage setpoint on generator 2 does not match the value at bus 1 [ Info: the voltage setpoint on generator 3 does not match the value at bus 3 [ Info: removing 1 cost terms from generator 4: [4000.0, 0.0] [ Info: removing 1 cost terms from generator 1: [1400.0, 0.0] [ Info: removing 1 cost terms from generator 5: [1000.0, 0.0] [ Info: removing 1 cost terms from generator 2: [1500.0, 0.0] [ Info: removing 3 cost terms from generator 6: Float64[] [ Info: removing 3 cost terms from generator 7: Float64[] [ Info: removing 1 cost terms from generator 3: [3000.0, 0.0] ┌ Info: Constructing System from Power Models │ data["name"] = "nesta_case5_pjm" └ data["source_type"] = "matpower" [ Info: Reading bus data [ Info: Reading generator data [ Info: Reading branch data ┌ Warning: Rate 1200.0 MW for bus2-bus3-i_4 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 ┌ Warning: Rate 200.0 MW for bus1-bus2-i_1 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 ┌ Warning: Rate 200.0 MW for bus1-bus4-i_2 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 ┌ Warning: Rate 200.0 MW for bus4-bus5-i_7 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 ┌ Warning: Rate 1000.0 MW for bus1-bus5-i_3 is larger than the max expected in the range of (min = 134.0, max = 145.0). └ @ PowerSystems ~/.julia/packages/PowerSystems/61h6O/src/utils/IO/branchdata_checks.jl:148 [ Info: Reading branch data [ Info: Reading DC Line data [ Info: Reading storage data ┌ Warning: no component category=Generator name=HydroDispatch1 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch2 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch3 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch1 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch3 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch1 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch3 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch1 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 ┌ Warning: no component category=Generator name=HydroDispatch3 └ @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/3LlGM/src/system_data.jl:478 [ Info: Serialized time series data to /Users/cbarrows/.julia/packages/PowerSystemCaseBuilder/4FIfo/data/serialized_system/ForecastOnly/5_bus_matpower_RT_time_series_storage.h5. [ Info: Serialized System to /Users/cbarrows/.julia/packages/PowerSystemCaseBuilder/4FIfo/data/serialized_system/ForecastOnly/5_bus_matpower_RT.json
Base Power: 100.0
Num components: 30
9 rows × 3 columns
ConcreteType | SuperTypes | Count | |
---|---|---|---|
String | String | Int64 | |
1 | Arc | Topology <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 6 |
2 | Area | AggregationTopology <: Topology <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 1 |
3 | Bus | Topology <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 5 |
4 | Line | ACBranch <: Branch <: Device <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 5 |
5 | LoadZone | AggregationTopology <: Topology <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 1 |
6 | PhaseShiftingTransformer | ACBranch <: Branch <: Device <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 2 |
7 | PowerLoad | StaticLoad <: ElectricLoad <: StaticInjection <: Device <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 3 |
8 | RenewableDispatch | RenewableGen <: Generator <: StaticInjection <: Device <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 2 |
9 | ThermalStandard | ThermalGen <: Generator <: StaticInjection <: Device <: Component <: InfrastructureSystemsComponent <: InfrastructureSystemsType <: Any | 5 |
Components with time series data: 5
Total StaticTimeSeries: 5
Total Forecasts: 5
Resolution: 60 minutes
First initial time: 2020-01-01T00:00:00
Last initial time: 2020-03-24T12:00:00
Horizon: 12
Interval: 60 minutes
Forecast window count: 2005
OperationsProblemTemplate
s¶template_uc = template_unit_commitment()
template_ed = template_economic_dispatch()
Operations Problem Specification ============================================ Transmission: CopperPlatePowerModel ============================================ Devices Models: Type: ThermalStandard Formulation: ThermalDispatch Type: HydroDispatch Formulation: HydroDispatchRunOfRiver Type: PowerLoad Formulation: StaticPowerLoad Type: RenewableFix Formulation: FixedOutput Type: RenewableDispatch Formulation: RenewableFullDispatch Type: HydroEnergyReservoir Formulation: HydroDispatchRunOfRiver Type: InterruptibleLoad Formulation: InterruptiblePowerLoad ============================================ Branches Models: Type: Line Formulation: StaticBranch Type: TapTransformer Formulation: StaticBranch Type: Transformer2W Formulation: StaticBranch Type: HVDCLine Formulation: HVDCDispatch ============================================ Services Models: Type: VariableReserve{ReserveDown} Formulation: RangeReserve Type: VariableReserve{ReserveUp} Formulation: RangeReserve ============================================
problems = SimulationProblems(
UC = OperationsProblem(
template_uc,
sys_DA,
optimizer = solver,
balance_slack_variables = true,
),
ED = OperationsProblem(
template_ed,
sys_RT,
optimizer = ipopt_solver,
constraint_duals = [:CopperPlateBalance],
),
)
feedforward_chronologies = Dict(("UC" => "ED") => Synchronize(periods = 24))
feedforward = Dict(
("ED", :devices, :ThermalStandard) => SemiContinuousFF(
binary_source_problem = ON,
affected_variables = [ACTIVE_POWER],
),
)
#cache = Dict("UC" => [TimeStatusChange(ThermalStandard, PSI.ON)])
intervals = Dict("UC" => (Hour(24), Consecutive()), "ED" => (Hour(1), Consecutive()))
DA_RT_sequence = SimulationSequence(
problems = problems,
intervals = intervals,
ini_cond_chronology = InterProblemChronology(),
feedforward_chronologies = feedforward_chronologies,
feedforward = feedforward,
)
Feed Forward Chronology ----------------------- ED: SemiContinuousFF -> ThermalStandard UC--┐ from : On | ┌----┬----┬----┬----┬----┼----┬----┬----┬----┬----┬----┐ | | | | | | | | | | | | | | | | | | | | | | | | └─ED └─ED └─ED └─ED └─ED └─ED └─ED └─ED └─ED └─ED └─ED └─ED ... (x24) to : ["P"] Initial Condition Chronology ---------------------------- 1 | | 2 --> 2 ... (x24)
Simulation
¶file_path = mkpath(joinpath(".", "5-bus-simulation"))
sim = Simulation(
name = "5bus-test",
steps = 1,
problems = problems,
sequence = DA_RT_sequence,
simulation_folder = file_path,
)
Simulation()
build!(sim)
┌ Info: │ ────────────────────────────────────────────────────────────────────────────── │ Time Allocations │ ────────────────────── ─────────────────────── │ Tot / % measured: 7.83s / 100% 874MiB / 100% │ │ Section ncalls time %tot avg alloc %tot avg │ ────────────────────────────────────────────────────────────────────────────── │ Build Simulation 1 7.83s 100% 7.83s 874MiB 100% 874MiB │ Build Problems 1 7.77s 99.3% 7.77s 863MiB 98.6% 863MiB │ Problem UC 1 7.09s 90.6% 7.09s 808MiB 92.4% 808MiB │ Services 1 3.04s 38.9% 3.04s 364MiB 41.6% 364MiB │ ThermalStandard 1 947ms 12.1% 947ms 98.2MiB 11.2% 98.2MiB │ RenewableDis... 1 739ms 9.45% 739ms 87.5MiB 10.0% 87.5MiB │ Interruptibl... 1 420ms 5.36% 420ms 47.3MiB 5.41% 47.3MiB │ HydroDispatch 1 301ms 3.85% 301ms 31.0MiB 3.54% 31.0MiB │ Build pre-step 1 189ms 2.41% 189ms 5.34MiB 0.61% 5.34MiB │ RenewableFix 1 123ms 1.58% 123ms 16.3MiB 1.87% 16.3MiB │ CopperPlateP... 1 109ms 1.39% 109ms 11.7MiB 1.34% 11.7MiB │ PowerLoad 1 4.06ms 0.05% 4.06ms 323KiB 0.04% 323KiB │ Line 1 236μs 0.00% 236μs 47.4KiB 0.01% 47.4KiB │ TapTransformer 1 141μs 0.00% 141μs 47.1KiB 0.01% 47.1KiB │ HydroEnergyR... 1 135μs 0.00% 135μs 4.92KiB 0.00% 4.92KiB │ Transformer2W 1 120μs 0.00% 120μs 47.1KiB 0.01% 47.1KiB │ HVDCLine 1 120μs 0.00% 120μs 48.1KiB 0.01% 48.1KiB │ Objective 1 75.0μs 0.00% 75.0μs 109KiB 0.01% 109KiB │ Problem ED 1 681ms 8.70% 681ms 54.5MiB 6.23% 54.5MiB │ ThermalStandard 1 67.4ms 0.86% 67.4ms 8.03MiB 0.92% 8.03MiB │ PowerLoad 1 3.24ms 0.04% 3.24ms 113KiB 0.01% 113KiB │ RenewableDis... 1 1.84ms 0.02% 1.84ms 229KiB 0.03% 229KiB │ Services 1 1.22ms 0.02% 1.22ms 53.0KiB 0.01% 53.0KiB │ CopperPlateP... 1 586μs 0.01% 586μs 288KiB 0.03% 288KiB │ Objective 1 398μs 0.01% 398μs 245KiB 0.03% 245KiB │ Build pre-step 1 128μs 0.00% 128μs 15.7KiB 0.00% 15.7KiB │ HydroDispatch 1 71.4μs 0.00% 71.4μs 4.72KiB 0.00% 4.72KiB │ RenewableFix 1 61.2μs 0.00% 61.2μs 4.72KiB 0.00% 4.72KiB │ HydroEnergyR... 1 45.6μs 0.00% 45.6μs 4.86KiB 0.00% 4.86KiB │ Interruptibl... 1 26.6μs 0.00% 26.6μs 4.78KiB 0.00% 4.78KiB │ Line 1 2.80μs 0.00% 2.80μs 64.0B 0.00% 64.0B │ TapTransformer 1 2.45μs 0.00% 2.45μs 64.0B 0.00% 64.0B │ HVDCLine 1 2.26μs 0.00% 2.26μs 64.0B 0.00% 64.0B │ Transformer2W 1 907ns 0.00% 907ns 64.0B 0.00% 64.0B │ Serializing Simu... 1 47.5ms 0.61% 47.5ms 11.3MiB 1.29% 11.3MiB │ Assign FeedForward 1 6.36ms 0.08% 6.36ms 404KiB 0.05% 404KiB │ Initialize Simul... 1 2.03ms 0.03% 2.03ms 20.7KiB 0.00% 20.7KiB │ Check Steps 1 11.0μs 0.00% 11.0μs 1.30KiB 0.00% 1.30KiB └ ──────────────────────────────────────────────────────────────────────────────
BuildStatus.BUILT = 0
execute!(sim, enable_progress_bar = false)
****************************************************************************** This program contains Ipopt, a library for large-scale nonlinear optimization. Ipopt is released as open source code under the Eclipse Public License (EPL). For more information visit https://github.com/coin-or/Ipopt ******************************************************************************
RunStatus.SUCCESSFUL = 0
# Results
First we can load the result metadata
results = SimulationResults(sim);
uc_results = get_problem_results(results, "UC")
ed_results = get_problem_results(results, "ED");
Then we can read and examine the results of interest
prices = read_dual(ed_results, :CopperPlateBalance)
or if we want to look at the realized values
read_realized_duals(ed_results)[:CopperPlateBalance]
note that in this simulation the prices are all equal to the balance slack penalty value of $100000/MWh because there is unserved energy in the result
This notebook was generated using Literate.jl.