begin
using AustralianElectricityMarkets
import AustralianElectricityMarkets.RegionModel as RM
using PowerSystems
using PowerSimulations
using HydroPowerSimulations
using StorageSystemsSimulations
using Chain
using DataFrames
using AlgebraOfGraphics, CairoMakie
using TidierDB
using Dates
using HiGHS
endAddition of batteries
In addition to thermal, renewable, and hydro generators, we now include storage units (batteries) in our market clearing problem. We use the EnergyReservoirStorage component and a StorageDispatchWithReserves model, which allows the optimizer to manage both charging and discharging while respecting energy limits.
Batteries in the NEM play an increasingly vital role. They can perform Arbitrage: charging when electricity prices are low (e.g., during the middle of the day when solar is abundant) and discharging when prices are high (e.g., during the evening peak). Furthermore, they provide essential services like FCAS (Frequency Control Ancillary Services) to keep the grid stable.
FCAS is a work in progress
This package does not support yet the definition of Ancillary Services consistent with the NEM rules. Stay tuned for the inclusion of those in the future
Setup the system
Initialise a connection to manage the market data via duckdb. In this example, we will look at a period in January 2025.
Get the data first!
You will first need to download the data from the monthly archive, saving them locally in parquet files.
tables = table_requirements(RegionalNetworkConfiguration())
map(tables) do table
fetch_table_data(table, Date(2025, 1, 1):Date(2025,1,31))
end;db = aem_connect(duckdb());AustralianElectricityMarkets.AEMDB(DuckDB.DB(":memory:"), HiveConfiguration("/home/runner/.nemweb_cache", "file"))Instantiate the system using a regional network configuration.
sys = nem_system(db, RegionalNetworkConfiguration())| System | |
| Property | Value |
|---|---|
| Name | |
| Description | |
| System Units Base | SYSTEM_BASE |
| Base Power | 100.0 |
| Base Frequency | 60.0 |
| Num Components | 602 |
| Static Components | |
| Type | Count |
|---|---|
| ACBus | 12 |
| Arc | 12 |
| Area | 6 |
| AreaInterchange | 8 |
| EnergyReservoirStorage | 31 |
| HydroDispatch | 84 |
| Line | 14 |
| PowerLoad | 6 |
| RenewableDispatch | 222 |
| ThermalStandard | 199 |
| TransmissionInterface | 8 |
Set the horizon and resolution for the simulation. Batteries are often more interesting to observe at higher resolutions or over longer periods where their energy constraints become relevant. Here we use a 30-minute interval over a 48-hour horizon.
interval = Minute(30)
horizon = Hour(48)
start_date = DateTime(2025, 1, 2, 4, 0)
date_range = start_date:interval:(start_date + horizon)
@show date_rangeDates.DateTime("2025-01-02T04:00:00"):Dates.Minute(30):Dates.DateTime("2025-01-04T04:00:00")Set deterministic time series for demand, renewables, hydro, and market bids.
set_demand!(sys, db, date_range; resolution = interval)
set_renewable_pv!(sys, db, date_range; resolution = interval)
set_renewable_wind!(sys, db, date_range; resolution = interval)
set_hydro_limits!(sys, db, date_range; resolution = interval)
set_market_bids!(sys, db, date_range; resolution = interval)[ Info: Setting loads to 0 for SNOWY1 Load
[ Info: Setting PV power time series
[ Info: Setting wind power time series
[ Info: Setting loads to 0 for EILDON3
[ Info: Setting loads to 0 for HLMSEW01
[ Info: Setting loads to 0 for PINDARI
[ Info: Setting loads to 0 for PALOONA
[ Info: Setting loads to 0 for KEEPIT
[ Info: Setting loads to 0 for RUBICON
[ Info: Setting loads to 0 for COPTNHYD
[ Info: Setting loads to 0 for PUMP2
[ Info: Setting loads to 0 for WYANGALA
[ Info: Setting loads to 0 for YWNGAHYD
[ Info: Setting loads to 0 for CLOVER
[ Info: Setting loads to 0 for ROWALLAN
[ Info: Setting loads to 0 for GUTHNL1
[ Info: Setting loads to 0 for GLENMAG1
[ Info: Setting loads to 0 for WYANGALB
[ Info: Setting loads to 0 for BROWNMT
[ Info: Setting loads to 0 for L_W_CNL1
[ Info: Setting loads to 0 for MURAYNL3
[ Info: Setting loads to 0 for BURRIN
[ Info: Setting loads to 0 for CLUNY
[ Info: Setting loads to 0 for PUMP1
[ Info: Setting loads to 0 for REPULSE
[ Info: Setting loads to 0 for KAREEYA5
[ Info: Setting loads to 0 for PO110NL1
[ Info: Setting loads to 0 for TUMT3NL2
[ Info: Setting loads to 0 for WYA252B1
[ Info: Setting loads to 0 for GLBWNHYD
[ Info: Setting loads to 0 for JOUNAMA1
[ Info: Setting loads to 0 for JNDABNE1
[ Info: Setting loads to 0 for SNOWYGJP
[ Info: Setting loads to 0 for GOVILLB1
[ Info: Setting loads to 0 for BAPS
[ Info: Setting loads to 0 for TUMT3NL1
[ Info: Setting loads to 0 for TRIBNL1
[ Info: Setting loads to 0 for THEDROP1
[ Info: Setting loads to 0 for ADPMH1
[ Info: Setting loads to 0 for MURAYNL2
[ Info: Setting loads to 0 for BUTLERSG
[ Info: Setting loads to 0 for TUMT3NL3
[ Info: Setting loads to 0 for BDONGHYD
[ Info: Setting loads to 0 for WILLHOV1
[ Info: Setting loads to 0 for MURAYNL1
[ Info: Setting loads to 0 for WYB252B1
┌ Warning: No bid data for generator APPIN, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator SHEP1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WINGF1_1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator DRYCNL, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator SNUGNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator STGEORG1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BOLIVAR1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GROSV1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CALLNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BBASEHOS, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TAHMOOR1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CLAYTON, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TORNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TOWER, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TABMILL2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator VICMILL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator EASTCRK, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TGNSS1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TATURA01, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator HALAMRD1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator JACKSGUL, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MORANBAH, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator HASTING1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator VPNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GRANGEAV, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TARNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator ERNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator EASTCRK2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GLADNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WILGB01, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator YWNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator LUCAS2S2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GERMCRK, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator LIDDNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MINTNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator OAKY2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MPNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WINGF2_1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator RPCG, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator LYNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator STAPYLTON1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator HASTING3, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WESTCBT1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WILGAPK, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CBWWDG1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BPLANDF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator INVICTA, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator ERGT01, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MBAHNTH, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator OAKYCREK, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WDLNGN01, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CBWWDG2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WOLLERT1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TATIARA1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WESTILL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BROOKLYN, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BWTR1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator ICSM, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator PIONEER, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator LUCASHGT, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GB01, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CBWWBG1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TITREE, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GLENNCRK, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GROSV2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator RACOMIL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator LONGFORD, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CONDONG1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BOWWDG1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator HASTING2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator STANNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator SHOAL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CULLRGWF, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator ROYALLA1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GRIFSF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MLWF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BARCSF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator PORTWF, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator NASF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CBWWPV1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CODRNGTON, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator YSWF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TOORAWF, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator VALDORA1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MLSP1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CBWWPV2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CHALLHWF, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WHILL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CESF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator DIAPURWF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator FSWF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WOOLNTH1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MAROOWF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator ADPPV2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CHPSTWF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WONWP, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator SKSF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BAKING1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator HUGSF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TIMWEST, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator LRSF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator YAMBUKWF, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WAUBRAWF, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator HEPWIND1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator YAWWF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator ADPPV3, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CBWF1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CAPTL_WF, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator EILDON3, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator HLMSEW01, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator PINDARI, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator PALOONA, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator KEEPIT, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator RUBICON, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator COPTNHYD, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator PUMP2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WYANGALA, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator YWNGAHYD, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CLOVER, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator ROWALLAN, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GUTHNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GLENMAG1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WYANGALB, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BROWNMT, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator L_W_CNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MURAYNL3, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BURRIN, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator CLUNY, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator PUMP1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator REPULSE, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator KAREEYA5, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator PO110NL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TUMT3NL2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WYA252B1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GLBWNHYD, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator JOUNAMA1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator JNDABNE1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator SNOWYGJP, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator GOVILLB1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BAPS, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TUMT3NL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TRIBNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator THEDROP1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator ADPMH1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MURAYNL2, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BUTLERSG, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator TUMT3NL3, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator BDONGHYD, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WILLHOV1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator MURAYNL1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator WYB252B1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:490
┌ Warning: No bid data for generator KESSB1, setting to unavailable.
└ @ AustralianElectricityMarkets ~/work/AustralianElectricityMarkets.jl/AustralianElectricityMarkets.jl/src/parser.jl:531Derive forecasts from the deterministic time series.
transform_single_time_series!(
sys,
horizon,
interval,
);
@show sys| System | |
| Property | Value |
|---|---|
| Name | |
| Description | |
| System Units Base | SYSTEM_BASE |
| Base Power | 100.0 |
| Base Frequency | 60.0 |
| Num Components | 602 |
| Static Components | |
| Type | Count |
|---|---|
| ACBus | 12 |
| Arc | 12 |
| Area | 6 |
| AreaInterchange | 8 |
| EnergyReservoirStorage | 31 |
| HydroDispatch | 84 |
| Line | 14 |
| PowerLoad | 6 |
| RenewableDispatch | 222 |
| ThermalStandard | 199 |
| TransmissionInterface | 8 |
| StaticTimeSeries Summary | |||||||
| owner_type | owner_category | name | time_series_type | initial_timestamp | resolution | count | time_step_count |
|---|---|---|---|---|---|---|---|
| String | String | String | String | String | Dates.CompoundPeriod | Int64 | Int64 |
| HydroDispatch | Component | max_active_power | SingleTimeSeries | 2025-01-02T04:00:00 | 30 minutes | 84 | 96 |
| PowerLoad | Component | max_active_power | SingleTimeSeries | 2025-01-02T04:00:00 | 30 minutes | 6 | 96 |
| RenewableDispatch | Component | max_active_power | SingleTimeSeries | 2025-01-02T04:00:00 | 30 minutes | 222 | 96 |
| 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 |
| EnergyReservoirStorage | Component | decremental_initial_input | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 30 | 2 days | empty period | 1 |
| EnergyReservoirStorage | Component | decremental_variable_cost | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 30 | 2 days | empty period | 1 |
| EnergyReservoirStorage | Component | incremental_initial_input | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 30 | 2 days | empty period | 1 |
| EnergyReservoirStorage | Component | variable_cost | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 30 | 2 days | empty period | 1 |
| HydroDispatch | Component | incremental_initial_input | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 41 | 2 days | empty period | 1 |
| HydroDispatch | Component | max_active_power | DeterministicSingleTimeSeries | 2025-01-02T04:00:00 | 30 minutes | 84 | 2 days | 30 minutes | 1 |
| HydroDispatch | Component | variable_cost | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 41 | 2 days | empty period | 1 |
| PowerLoad | Component | max_active_power | DeterministicSingleTimeSeries | 2025-01-02T04:00:00 | 30 minutes | 6 | 2 days | 30 minutes | 1 |
| RenewableDispatch | Component | incremental_initial_input | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 186 | 2 days | empty period | 1 |
| RenewableDispatch | Component | max_active_power | DeterministicSingleTimeSeries | 2025-01-02T04:00:00 | 30 minutes | 222 | 2 days | 30 minutes | 1 |
| RenewableDispatch | Component | variable_cost | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 186 | 2 days | empty period | 1 |
| ThermalStandard | Component | incremental_initial_input | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 127 | 2 days | empty period | 1 |
| ThermalStandard | Component | variable_cost | Deterministic | 2025-01-02T04:00:00 | 30 minutes | 127 | 2 days | empty period | 1 |
Setup the problem
begin
template = ProblemTemplate()
set_device_model!(template, Line, StaticBranch)
set_device_model!(template, PowerLoad, StaticPowerLoad)
set_device_model!(template, RenewableDispatch, RenewableFullDispatch)
set_device_model!(template, ThermalStandard, ThermalBasicUnitCommitment)
set_device_model!(template, HydroDispatch, HydroDispatchRunOfRiver)
set_network_model!(template, NetworkModel(AreaBalancePowerModel; use_slacks = true))
set_device_model!(template, AreaInterchange, StaticBranch)
storage_model = DeviceModel(
EnergyReservoirStorage,
StorageDispatchWithReserves;
attributes = Dict(
"reservation" => true,
"energy_target" => false,
"cycling_limits" => false,
"regularization" => false,
),
)
set_device_model!(template, storage_model)
template
end| Network Model | |
| Network Model | PowerSimulations.AreaBalancePowerModel |
| Slacks | true |
| PTDF | false |
| Duals | None |
| HVDC Network Model | None |
| Device Models | ||
| Device Type | Formulation | Slacks |
|---|---|---|
| PowerSystems.ThermalStandard | PowerSimulations.ThermalBasicUnitCommitment | false |
| PowerSystems.PowerLoad | PowerSimulations.StaticPowerLoad | false |
| PowerSystems.RenewableDispatch | PowerSimulations.RenewableFullDispatch | false |
| PowerSystems.EnergyReservoirStorage | StorageSystemsSimulations.StorageDispatchWithReserves | false |
| PowerSystems.HydroDispatch | HydroPowerSimulations.HydroDispatchRunOfRiver | false |
| Branch Models | ||
| Branch Type | Formulation | Slacks |
|---|---|---|
| PowerSystems.AreaInterchange | PowerSimulations.StaticBranch | false |
| PowerSystems.Line | PowerSimulations.StaticBranch | false |
The dispatch problem is solved using the HiGHS solver.
solver = optimizer_with_attributes(HiGHS.Optimizer, "mip_rel_gap" => 0.05)
problem = DecisionModel(template, sys; optimizer = solver, horizon = horizon)
build!(problem; output_dir = joinpath(tempdir(), "out"))InfrastructureSystems.Optimization.ModelBuildStatusModule.ModelBuildStatus.BUILT = 0Solve the problem:
solve!(problem)InfrastructureSystems.Simulation.RunStatusModule.RunStatus.SUCCESSFULLY_FINALIZED = 0Observe the results:
res = OptimizationProblemResults(problem)Start: 2025-01-02T04:00:00
End: 2025-01-04T03:30:00
Resolution: 30 minutes
| PowerSimulations Problem Auxiliary variables Results |
| StorageEnergyOutput__EnergyReservoirStorage |
| TimeDurationOff__ThermalStandard |
| TimeDurationOn__ThermalStandard |
| HydroEnergyOutput__HydroDispatch |
| PowerSimulations Problem Expressions Results |
| ProductionCostExpression__ThermalStandard |
| ActivePowerBalance__Area |
| ProductionCostExpression__HydroDispatch |
| ProductionCostExpression__RenewableDispatch |
| PowerSimulations Problem Parameters Results |
| IncrementalPiecewiseLinearSlopeParameter__RenewableDispatch |
| IncrementalPiecewiseLinearBreakpointParameter__EnergyReservoirStorage |
| ActivePowerTimeSeriesParameter__HydroDispatch |
| ActivePowerTimeSeriesParameter__PowerLoad |
| IncrementalPiecewiseLinearBreakpointParameter__RenewableDispatch |
| IncrementalPiecewiseLinearBreakpointParameter__ThermalStandard |
| IncrementalCostAtMinParameter__ThermalStandard |
| DecrementalPiecewiseLinearSlopeParameter__EnergyReservoirStorage |
| DecrementalPiecewiseLinearBreakpointParameter__EnergyReservoirStorage |
| IncrementalPiecewiseLinearBreakpointParameter__HydroDispatch |
| IncrementalPiecewiseLinearSlopeParameter__ThermalStandard |
| ActivePowerTimeSeriesParameter__RenewableDispatch |
| IncrementalPiecewiseLinearSlopeParameter__EnergyReservoirStorage |
| IncrementalPiecewiseLinearSlopeParameter__HydroDispatch |
| PowerSimulations Problem Variables Results |
| ActivePowerInVariable__EnergyReservoirStorage |
| ActivePowerVariable__HydroDispatch |
| OnVariable__ThermalStandard |
| StartVariable__ThermalStandard |
| EnergyVariable__EnergyReservoirStorage |
| ActivePowerVariable__ThermalStandard |
| ReservationVariable__EnergyReservoirStorage |
| ActivePowerOutVariable__EnergyReservoirStorage |
| SystemBalanceSlackUp__Area |
| SystemBalanceSlackDown__Area |
| FlowActivePowerVariable__AreaInterchange |
| ActivePowerVariable__RenewableDispatch |
| StopVariable__ThermalStandard |
Battery Behavior: BOWWBA1
Let's focus on the behavior of a specific battery, "BOWWBA1" (Bolivar Waste Water Treatment BESS), located in South Australia. South Australia is a world leader in battery integration, often relying on them to manage its high penetration of wind and solar.
We can examine the battery's charging (ActivePowerIn) and discharging (ActivePowerOut) cycles.
begin
batteries_in = read_variable(res, "ActivePowerInVariable__EnergyReservoirStorage")
batteries_out = read_variable(res, "ActivePowerOutVariable__EnergyReservoirStorage")
batteries_all = vcat(
insertcols(batteries_in, :direction => "in"),
insertcols(batteries_out, :direction => "out"),
)
bowwba1_power = subset(batteries_all, :name => ByRow(==("BOWWBA1")))
plt = data(bowwba1_power) *
mapping(:DateTime, :value, color = :direction) *
visual(Lines)
draw(plt; figure = (; size = (800, 400), title = "BOWWBA1 Active Power (MW)"))
end
We can also look at the State of Charge (SOC) of the battery over the simulation period to see how it fills and empties.
begin
soc = read_variable(res, "EnergyVariable__EnergyReservoirStorage")
bowwba1_soc = subset(soc, :name => ByRow(==("BOWWBA1")))
plt = data(bowwba1_soc) *
mapping(:DateTime, :value) *
visual(Lines)
draw(plt; figure = (; size = (800, 400), title = "BOWWBA1 State of Charge (MWh)"))
end
Regional Dispatch with Storage
Finally, let's see how batteries integrate into the overall generation mix across the regions. In the NEM's regulatory framework, batteries were historically treated as both a generator and a load. More recently, new categories like the Integrated Resource Provider (IRP) have been introduced to better reflect their dual nature.
In our results, batteries appear as a source of energy when discharging and a consumer of energy when charging.
begin
function filter_non_all_zero(df, group_by)
gdf = groupby(df, group_by)
is_all_zero = combine(gdf, :value => (x -> all(x == 0)) => :all_zero)
subset!(is_all_zero, :all_zero => x -> .!x)
return innerjoin(df, is_all_zero, on = group_by)
end
renewables = read_variable(res, "ActivePowerVariable__RenewableDispatch")
thermal = read_variable(res, "ActivePowerVariable__ThermalStandard")
hydro = read_variable(res, "ActivePowerVariable__HydroDispatch")
## Calculate net battery dispatch
batteries_tot = @chain innerjoin(batteries_in, batteries_out, on = [:DateTime, :name]; makeunique = true) begin
select!(:DateTime, :name, [:value, :value_1] => ((in_, out_) -> out_ - in_) => :value)
end
gens_long = vcat(renewables, thermal, hydro, batteries_tot)
select!(gens_long, :DateTime, :name => :DUID, :value)
by_fuel = @chain select(
read_units(db),
[:DUID, :STATIONID, :CO2E_ENERGY_SOURCE, :REGIONID]
) begin
rightjoin(gens_long, on = :DUID)
groupby([:CO2E_ENERGY_SOURCE, :REGIONID, :DateTime])
combine(:value => sum => :value)
subset(:value => ByRow(!=(0.0)))
dropmissing!
select!(
:DateTime, :REGIONID, :CO2E_ENERGY_SOURCE => :Source, :value
)
end
loads = @chain res begin
read_parameter("ActivePowerTimeSeriesParameter__PowerLoad")
transform!(
:name => ByRow(x -> split(x, " ")[1]) => :REGIONID
)
subset!(:REGIONID => ByRow(!=("SNOWY1")))
insertcols!(
:Source => "Region demand"
)
select!(
:DateTime, :REGIONID, :Source,
:value => ByRow(-) => :value
)
end
mapping_ = mapping(:DateTime, :value, color = :Source, layout = :REGIONID)
demand = data(loads) * mapping_ * visual(Lines, linestyle = (:dash, :dense))
generation = data(by_fuel) * mapping_ * visual(Lines)
draw(
demand + generation,
scales(Color = (; palette = :tab10));
figure = (; size = (1000, 800)),
legend = (; position = :bottom),
)
end