SIIP Tutorial

Time-varying bid problems with PowerSimulations.jl

Originally Contributed by: Sourabh Dalvi

Introduction

PowerSimulations.jl supports the construction of Operations problems in power system with three part cost bids for each time step. MarketBidCost allows the user to pass a time-series of variable cost for energy and ancillary services jointly. This example shows how to build a Operations problem with MarketBidCost and how to add the time-series data to the devices.

Dependencies

Modeling Packages

using PowerSystems
using PowerSimulations
const PSI = PowerSimulations
PowerSimulations

Data management packages

using PowerSystemCaseBuilder
using Dates
using DataFrames
using TimeSeries

Optimization packages

using HiGHS #solver

Data

Create a System from RTS-GMLC data

sys = build_system(PSITestSystems, "modified_RTS_GMLC_DA_sys")
System
Property Value
System Units Base SYSTEM_BASE
Base Power 100.0
Base Frequency 60.0
Num Components 500
Static Components
Type Count Has Static Time Series Has Forecasts
Arc 109 false false
Area 3 true true
Bus 73 false false
FixedAdmittance 3 true true
HydroDispatch 1 true true
Line 105 false false
LoadZone 21 false false
PowerLoad 51 true true
RenewableDispatch 29 true true
RenewableFix 31 true true
TapTransformer 15 false false
ThermalStandard 54 false false
VariableReserve{PowerSystems.ReserveDown} 1 true true
VariableReserve{PowerSystems.ReserveUp} 4 true true
Time Series Summary
Property Value
Components with time series data 123
Total StaticTimeSeries 124
Total Forecasts 124
Resolution 60 minutes
First initial time 2020-01-01T00:00:00
Last initial time 2020-12-30T00:00:00
Horizon 48
Interval 1440 minutes
Forecast window count 365

Creating the Time Series data for Energy bid

MultiDay = collect(
    DateTime("2020-01-01T00:00:00"):Hour(1):(DateTime("2020-01-01T00:00:00") + Hour(8783)),
);

Adding a MarketBidCost time series

Here we add the energy bid time series to the system. The TimeSeriesData that holds the energy bid data can be of any type (i.e. SingleTimeSeries or Deterministic), but it has to be consistent with the existing data in the sys. So, we'll first remove the existing DeterministicSingleTimeSeries, then add the bid time series as SingleTimeSeries, then re-transform all of the time series in sys.

remove_time_series!(sys, DeterministicSingleTimeSeries)

for gen in get_components(ThermalGen, sys)
    varcost = get_operation_cost(gen)
    data = TimeArray(MultiDay, repeat([get_cost(get_variable(varcost))], 8784))
    _time_series = SingleTimeSeries("variable_cost", data)
    add_time_series!(sys, gen, _time_series)
    #set_variable_cost!(sys, gen, _time_series)
end

Transforming SingleTimeSeries into Deterministic

transform_single_time_series!(sys, 24, Dates.Hour(24))

In the OperationsProblem example we defined a unit-commitment problem with a copper plate representation of the network. Here, we want do define unit-commitment problem with ThermalMultiStartUnitCommitment formulation for thermal device representation.

For now, let's just choose a standard UC formulation.

uc_template = template_unit_commitment()
Network Model
Network Model PowerSimulations.CopperPlatePowerModel
Slacks false
PTDF false
Duals
Device Models ┌───────────────────────────────────┬─────────────────────────────────────────────┬────────┐ │ Device Type │ Formulation │ Slacks │ ├───────────────────────────────────┼─────────────────────────────────────────────┼────────┤ │ PowerSystems.ThermalStandard │ PowerSimulations.ThermalBasicUnitCommitment │ false │ │ PowerSystems.HydroEnergyReservoir │ PowerSimulations.HydroDispatchRunOfRiver │ false │ │ PowerSystems.RenewableDispatch │ PowerSimulations.RenewableFullDispatch │ false │ │ PowerSystems.PowerLoad │ PowerSimulations.StaticPowerLoad │ false │ │ PowerSystems.InterruptibleLoad │ PowerSimulations.InterruptiblePowerLoad │ false │ │ PowerSystems.RenewableFix │ PowerSimulations.FixedOutput │ false │ │ PowerSystems.HydroDispatch │ PowerSimulations.HydroDispatchRunOfRiver │ false │ └───────────────────────────────────┴─────────────────────────────────────────────┴────────┘
Branch Models
Branch Type Formulation Slacks
PowerSystems.Transformer2W PowerSimulations.StaticBranch false
PowerSystems.Line PowerSimulations.StaticBranch false
PowerSystems.HVDCLine PowerSimulations.HVDCDispatch false
PowerSystems.TapTransformer PowerSimulations.StaticBranch false
Service Models
Service Type Formulation Slacks Aggregated Model
PowerSystems.VariableReserve{PowerSystems.ReserveUp} PowerSimulations.RangeReserve false true
PowerSystems.VariableReserve{PowerSystems.ReserveDown} PowerSimulations.RangeReserve false true

And adjust the thermal generator formulation to use ThermalMultiStartUnitCommitment

set_device_model!(uc_template, ThermalMultiStart, ThermalMultiStartUnitCommitment)

Now we can build a 4-hour economic dispatch problem with the RTS data.

solver = optimizer_with_attributes(HiGHS.Optimizer, "mip_rel_gap" => 0.5)

problem = DecisionModel(uc_template, sys, horizon = 4, optimizer = solver)
build!(problem, output_dir = mktempdir())
PowerSimulations.BuildStatusModule.BuildStatus.BUILT = 0

And solve it ...

solve!(problem)
PowerSimulations.RunStatusModule.RunStatus.SUCCESSFUL = 0
CC BY-SA 4.0 "Dheepak Krishnamurthy". Last modified: August 26, 2022. Website built with Franklin.jl and the Julia programming language.