diff --git a/Project.toml b/Project.toml index 6aed9fb..0337056 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "FullNetworkSystems" uuid = "877b7152-b508-43dc-81fb-72341a693988" authors = ["Invenia Technical Computing Corporation"] -version = "1.0.0-DEV" +version = "1.0.0" [deps] AxisKeys = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5" diff --git a/docs/Manifest.toml b/docs/Manifest.toml index 1b9d8e6..6f41f3c 100644 --- a/docs/Manifest.toml +++ b/docs/Manifest.toml @@ -1,6 +1,6 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.7.1" +julia_version = "1.7.2" manifest_format = "2.0" [[deps.ANSIColoredPrinters]] @@ -25,9 +25,9 @@ uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" [[deps.ArrayInterface]] deps = ["Compat", "IfElse", "LinearAlgebra", "Requires", "SparseArrays", "Static"] -git-tree-sha1 = "c933ce606f6535a7c7b98e1d86d5d1014f730596" +git-tree-sha1 = "81f0cb60dc994ca17f68d9fb7c942a5ae70d9ee4" uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "5.0.7" +version = "5.0.8" [[deps.Artifacts]] uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" @@ -49,9 +49,9 @@ version = "1.14.0" [[deps.ChangesOfVariables]] deps = ["ChainRulesCore", "LinearAlgebra", "Test"] -git-tree-sha1 = "bf98fa45a0a4cee295de98d4c1462be26345b9a1" +git-tree-sha1 = "1e315e3f4b0b7ce40feded39c73049692126cf53" uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" -version = "0.1.2" +version = "0.1.3" [[deps.Compat]] deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] @@ -70,15 +70,15 @@ uuid = "587fd27a-f159-11e8-2dae-1979310e6154" version = "0.2.7" [[deps.DataAPI]] -git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8" +git-tree-sha1 = "fb5f5316dd3fd4c5e7c30a24d50643b73e37cd40" uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" -version = "1.9.0" +version = "1.10.0" [[deps.DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "3daef5523dd2e769dad2365274f760ff5f282c7d" +git-tree-sha1 = "cc1a8e22627f33c789ab60b36a9132ac050bbf75" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.11" +version = "0.18.12" [[deps.DataValueInterfaces]] git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" @@ -93,6 +93,12 @@ uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" deps = ["Mmap"] uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" +[[deps.Dictionaries]] +deps = ["Indexing", "Random"] +git-tree-sha1 = "0340cee29e3456a7de968736ceeb705d591875a2" +uuid = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4" +version = "0.3.20" + [[deps.Distributed]] deps = ["Random", "Serialization", "Sockets"] uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" @@ -105,9 +111,9 @@ version = "0.8.6" [[deps.Documenter]] deps = ["ANSIColoredPrinters", "Base64", "Dates", "DocStringExtensions", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"] -git-tree-sha1 = "6edbf28671b4df4f692e54ae72f1e35851cfbf38" +git-tree-sha1 = "122d031e8dcb2d3e767ed434bc4d1ae1788b5a7f" uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "0.27.16" +version = "0.27.17" [[deps.Downloads]] deps = ["ArgTools", "LibCURL", "NetworkOptions"] @@ -120,7 +126,7 @@ uuid = "da5c29d0-fa7d-589e-88eb-ea29b0a81949" version = "1.5.0" [[deps.FullNetworkSystems]] -deps = ["AxisKeys", "Dates", "DocStringExtensions", "InlineStrings"] +deps = ["AxisKeys", "Dates", "Dictionaries", "DocStringExtensions", "InlineStrings"] path = ".." uuid = "877b7152-b508-43dc-81fb-72341a693988" version = "1.0.0" @@ -136,6 +142,11 @@ git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1" uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" version = "0.1.1" +[[deps.Indexing]] +git-tree-sha1 = "ce1566720fd6b19ff3411404d4b977acd4814f9f" +uuid = "313cdc1a-70c2-5d6a-ae34-0150d3930a38" +version = "1.1.1" + [[deps.InlineStrings]] deps = ["Parsers"] git-tree-sha1 = "61feba885fac3a407465726d0c330b3055df897f" @@ -154,9 +165,9 @@ version = "0.5.4" [[deps.InverseFunctions]] deps = ["Test"] -git-tree-sha1 = "91b5dcf362c5add98049e6c29ee756910b03051d" +git-tree-sha1 = "336cc738f03e069ef2cac55a104eb823455dca75" uuid = "3587e190-3f89-42d0-90ee-14403ec27112" -version = "0.1.3" +version = "0.1.4" [[deps.InvertedIndices]] git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f" @@ -210,9 +221,9 @@ uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[deps.LogExpFunctions]] deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "a970d55c2ad8084ca317a4658ba6ce99b7523571" +git-tree-sha1 = "76c987446e8d555677f064aaac1145c4c17662f8" uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.12" +version = "0.3.14" [[deps.Logging]] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" @@ -254,9 +265,9 @@ uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" [[deps.OffsetArrays]] deps = ["Adapt"] -git-tree-sha1 = "043017e0bdeff61cfbb7afeb558ab29536bbb5ed" +git-tree-sha1 = "aee446d0b3d5764e35289762f6a18e8ea041a592" uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -version = "1.10.8" +version = "1.11.0" [[deps.OpenBLAS_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] @@ -269,9 +280,9 @@ version = "1.4.1" [[deps.Parsers]] deps = ["Dates"] -git-tree-sha1 = "621f4f3b4977325b9128d5fae7a8b4829a0c2222" +git-tree-sha1 = "1285416549ccfcdf0c50d4997a94331e88d68413" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.2.4" +version = "2.3.1" [[deps.Pkg]] deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] @@ -320,9 +331,9 @@ uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [[deps.Static]] deps = ["IfElse"] -git-tree-sha1 = "87e9954dfa33fd145694e42337bdd3d5b07021a6" +git-tree-sha1 = "5309da1cdef03e95b73cd3251ac3a39f887da53e" uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" -version = "0.6.0" +version = "0.6.4" [[deps.Statistics]] deps = ["LinearAlgebra", "SparseArrays"] @@ -330,9 +341,9 @@ uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [[deps.StatsAPI]] deps = ["LinearAlgebra"] -git-tree-sha1 = "8d7530a38dbd2c397be7ddd01a424e4f411dcc41" +git-tree-sha1 = "c82aaa13b44ea00134f8c9c89819477bd3986ecd" uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" -version = "1.2.2" +version = "1.3.0" [[deps.StatsBase]] deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] diff --git a/src/FullNetworkSystems.jl b/src/FullNetworkSystems.jl index 6124e04..7db6e38 100644 --- a/src/FullNetworkSystems.jl +++ b/src/FullNetworkSystems.jl @@ -10,7 +10,17 @@ export System, SystemDA, SystemRT export Zone, Generator, Bus, Branch export GeneratorTimeSeries, GeneratorStatus, GeneratorStatusDA, GeneratorStatusRT export gens_per_zone, branches_by_breakpoints, get_datetimes +export get_zones, get_buses, get_generators, get_branches +export get_regulation_requirements, get_operating_reserve_requirements, get_good_utility_requirements +export get_gens_per_bus, get_loads_per_bus, get_incs_per_bus, get_decs_per_bus, get_psds_per_bus +export get_ptdf, get_lodf +export get_initial_commitment, get_bids, get_availability, get_must_run +export get_initial_generation, get_load, get_offer_curve +export get_pmin, get_pmax, get_regmin, get_regmax +export get_regulation, get_spinning, get_supplemental_on, get_supplemental_off +export get_commitment, get_regulation_commitment include("system.jl") +include("accessors.jl") end diff --git a/src/accessors.jl b/src/accessors.jl new file mode 100644 index 0000000..9f6d0fa --- /dev/null +++ b/src/accessors.jl @@ -0,0 +1,144 @@ +""" + get_datetimes(system) + +Extract datetimes from a `System`. +""" +function get_datetimes(system::System) + # use offer_curve axiskeys because all subtypes of System have offer_curve + return axiskeys(system.generator_time_series.offer_curve, 2) +end + +get_zones(system::System) = system.zones + +"Returns a `Dictionary` with zonal regulation requirements indexed by zone number." +function get_regulation_requirements(system::System) + return map(system.zones) do zone + zone.regulation + end +end + +"Returns a `Dictionary` with zonal operating reserve requirements indexed by zone number." +function get_operating_reserve_requirements(system::System) + return map(system.zones) do zone + zone.operating_reserve + end +end + +"Returns a `Dictionary` with zonal good utility practice requirements indexed by zone number." +function get_good_utility_requirements(system::System) + return map(system.zones) do zone + zone.good_utility + end +end + +"Returns a `Dictionary` of `Bus` objects in the `System` indexed by bus name." +get_buses(system::System) = system.buses +"Returns a `Dictionary` of `Generator` objects in the `System` indexed by unit code." +get_generators(system::System) = system.generators +"Returns a `Dictionary` of `Branch` objects in the `System` indexed by branch name." +get_branches(system::System) = system.branches + +"Returns a `Dictionary` of unit codes at each bus." +get_gens_per_bus(system::System) = system.gens_per_bus +"Returns a `Dictionary` of load names at each bus." +get_loads_per_bus(system::System) = system.loads_per_bus + +"Returns the power transfer distribution factor of the system." +get_ptdf(system::System) = system.ptdf +"Returns the line outage distribution factor matrix of the system for a set of contingencies." +get_lodf(system::System) = system.lodf + +"Returns the generation of the generator at the start of the time period (MW)" +get_initial_generation(system::System) = system.generator_time_series.initial_generation +"Returns time series data of the load in the system" +get_load(system::System) = system.loads +"Returns time series data of the generator offer curves" +get_offer_curve(system::System) = system.generator_time_series.offer_curve +"Returns time series data of minimum generator output (MW)" +get_pmin(system::System) = system.generator_time_series.pmin +"Returns time series data of maximum generator output (MW)" +get_pmax(system::System) = system.generator_time_series.pmax +"Returns time series data of minimum generator output in the ancillary services market (MW)" +get_regmin(system::System) = system.generator_time_series.regulation_min +"Returns time series data of maximum generator output in the ancillary services market (MW)" +get_regmax(system::System) = system.generator_time_series.regulation_max + +"Returns time series data of offer prices for ancillary servives regulation (\$ /MW)" +get_regulation(system::System) = system.generator_time_series.asm_regulation +"Returns time series data of offer prices for ancillary servives spinning (\$ /MW)" +get_spinning(system::System) = system.generator_time_series.asm_spin +"Returns time series data of offer prices for ancillary servives supplemental on (\$ /MW)" +get_supplemental_on(system::System) = system.generator_time_series.asm_sup_on +"Returns time series data of offer prices for ancillary servives supplemental off (\$ /MW)" +get_supplemental_off(system::System) = system.generator_time_series.asm_sup_off + +"Returns a flag indicating whether each generator was on at the start of the day." +function get_initial_commitment(system::SystemDA) + return map(system.generator_time_series.initial_generation) do i + i == 0.0 ? false : true + end +end + +"Returns a `Dictionary` of increment bids at each bus." +get_incs_per_bus(system::SystemDA) = system.incs_per_bus +"Returns a `Dictionary` of decrement bids at each bus." +get_decs_per_bus(system::SystemDA) = system.decs_per_bus +"Returns a `Dictionary` of price sensitive demand bids at each bus." +get_psds_per_bus(system::SystemDA) = system.psds_per_bus + +""" +Returns time series data of bids for the bid type indicated. Bid type must be one of +`:increment`, `:decrement` or `:price_sensitive_demand`. +""" +function get_bids(system::SystemDA, type_of_bid::Symbol) + return getproperty(system, type_of_bid) +end + +"Returns time series data of flags indicating if the generator is available to be committed in each hour" +get_availability(system::SystemDA) = system.generator_status.availability +"Returns time series data of flags indicating if the generator must be committed in each hour" +get_must_run(system::SystemDA) = system.generator_status.must_run + +"Returns time series data of generator status in each hour" +get_commitment(system::SystemRT) = system.generator_status.status +"Returns time series data of generator regulation status in each hour" +get_regulation_commitment(system::SystemRT) = system.generator_status.status_regulation + +""" + gens_per_zone(system::System) + +Returns a `Dict` with keys of `Zone` numbers and values of generator names in that zone. +""" +function gens_per_zone(system::System) + gens_per_zone = Dict{Int, Vector{Int}}() + for gen in system.generators + if haskey(gens_per_zone, gen.zone) + push!(gens_per_zone[gen.zone], gen.unit_code) + else + gens_per_zone[gen.zone] = [gen.unit_code] + end + end + gens_per_zone[MARKET_WIDE_ZONE] = collect(keys(system.generators)) + return gens_per_zone +end + +""" + branches_by_breakpoints(system::System) + +Returns three vectors containing of the names of branches which have 0, 1, and 2 breakpoints. +""" +function branches_by_breakpoints(system::System) + zero_bp, one_bp, two_bp = String[], String[], String[] + for branch in system.branches + if branch.is_monitored + if all(branch.break_points .== 0.0) + push!(zero_bp, branch.name) + elseif last(branch.break_points) == 0.0 + push!(one_bp, branch.name) + else + push!(two_bp, branch.name) + end + end + end + return zero_bp, one_bp, two_bp +end diff --git a/src/system.jl b/src/system.jl index 81fc2c8..d57b9c5 100644 --- a/src/system.jl +++ b/src/system.jl @@ -1,3 +1,4 @@ +const MARKET_WIDE_ZONE = -9999 """ $TYPEDEF @@ -11,13 +12,11 @@ struct Zone "Zone number" number::Int64 "Zonal regulation requirement (MW)" - reg::Float64 - "Zonal spinning requirement (MW)" - spin::Float64 - "Zonal supplemental on requirement (MW)" - sup_on::Float64 - "Zonal supplemental off requirement (MW)" - sup_off::Float64 + regulation::Float64 + "Zonal operating reserve requirement (regulation + spinning + supplemental) (MW)" + operating_reserve::Float64 + "Zonal good utility practice requirement (regulation + spinning) (MW)" + good_utility::Float64 end ###### Static Component Types ###### @@ -125,14 +124,26 @@ struct GeneratorTimeSeries pmin::KeyedArray{Float64, 2} "Generator maximum output (MW)" pmax::KeyedArray{Float64, 2} - "Ancillary services regulation offer prices (\$ /MW)" - asm_regulation::KeyedArray{Float64, 2} - "Ancillary services spinning offer prices (\$ /MW)" - asm_spin::KeyedArray{Float64, 2} - "Ancillary services supplemental on offer prices (\$ /MW)" - asm_sup_on::KeyedArray{Float64, 2} - "Ancillary services supplemental off offer prices (\$ /MW)" - asm_sup_off::KeyedArray{Float64, 2} + """ + Ancillary services regulation offer prices (\$ /MW). Generators not providing the service + will have `missing` offer data + """ + asm_regulation::KeyedArray{Union{Missing, Float64}, 2} + """ + Ancillary services spinning offer prices (\$ /MW). Generators not providing the service + will have `missing` offer data + """ + asm_spin::KeyedArray{Union{Missing, Float64}, 2} + """ + Ancillary services supplemental on offer prices (\$ /MW). Generators not providing the service + will have `missing` offer data + """ + asm_sup_on::KeyedArray{Union{Missing, Float64}, 2} + """ + Ancillary services supplemental off offer prices (\$ /MW). Generators not providing the service + will have `missing` offer data + """ + asm_sup_off::KeyedArray{Union{Missing, Float64}, 2} end """ @@ -153,7 +164,7 @@ $TYPEDFIELDS struct GeneratorStatusDA <: GeneratorStatus "Hours each generator has been at its current status at the start of the day" hours_at_status::KeyedArray{Float64, 1} - "Flag indicating if generator is available to be committed in each hour" + "Flag indicating if the generator is available to be committed in each hour" availability::KeyedArray{Bool, 2} "Flag indicating if the generator must be committed in each hour" must_run::KeyedArray{Bool, 2} @@ -168,9 +179,9 @@ Fields: $TYPEDFIELDS """ struct GeneratorStatusRT <: GeneratorStatus - "Generator status indicated by a `Bool`" + "Generator commitment status indicated by a `Bool`" status::KeyedArray{Bool, 2} - "Generator regulation status indicated by a `Bool`" + "Generator regulation commitment status indicated by a `Bool`" status_regulation::KeyedArray{Bool, 2} end @@ -223,12 +234,12 @@ struct SystemDA <: System by the keys of the `Dictionary`. Each entry is a `KeyedArray` with axis keys `branch names x branch on outage` """ - LODF::Dictionary{String, KeyedArray{Float64, 2}} + lodf::Dictionary{String, KeyedArray{Float64, 2}} """ Power transfer distribution factor of the system. `KeyedArray` where the axis keys are `branch names x bus names` """ - PTDF::KeyedArray{Float64, 2} + ptdf::KeyedArray{Float64, 2} # Generator related time series "Generator related time series data" @@ -276,12 +287,12 @@ struct SystemRT <: System by the keys of the `Dictionary`. Each entry is a `KeyedArray` with axis keys `branch names x branch on outage` """ - LODF::Dictionary{String, KeyedArray{Float64, 2}} + lodf::Dictionary{String, KeyedArray{Float64, 2}} """ Power transfer distribution factor of the system. `KeyedArray` where the axis keys are `branch names x bus names` """ - PTDF::KeyedArray{Float64, 2} + ptdf::KeyedArray{Float64, 2} # Generator related time series "Generator related time series data" @@ -312,57 +323,9 @@ function Base.show(io::IO, ::MIME"text/plain", system::T) where {T <: System} for name in fieldnames(type) print(io, "$name, ") end - elseif type <: KeyedArray && name != :PTDF + elseif type <: KeyedArray && name != :ptdf print(io, "$name, ") end end return nothing end - -""" - get_datetimes(system) - -Extract datetimes from a `System`. -""" -function get_datetimes(system::System) - # use offer_curve axiskeys because all subtypes of System have offer_curve - return axiskeys(system.generator_time_series.offer_curve, 2) -end - -""" - gens_per_zone(system::System) - -Returns a `Dict` with keys of `Zone` numbers and values of generator names in that zone. -""" -function gens_per_zone(system::System) - gens_per_zone = Dict{Int, Vector{Int}}() - for gen in system.generators - if haskey(gens_per_zone, gen.zone) - push!(gens_per_zone[gen.zone], gen.unit_code) - else - gens_per_zone[gen.zone] = [gen.unit_code] - end - end - return gens_per_zone -end - -""" - branches_by_breakpoints(system::System) - -Returns three vectors containing of the names of branches which have 0, 1, and 2 breakpoints. -""" -function branches_by_breakpoints(system::System) - zero_bp, one_bp, two_bp = String[], String[], String[] - for branch in system.branches - if branch.is_monitored - if all(branch.break_points .== 0.0) - push!(zero_bp, branch.name) - elseif last(branch.break_points) == 0.0 - push!(one_bp, branch.name) - else - push!(two_bp, branch.name) - end - end - end - return zero_bp, one_bp, two_bp -end diff --git a/test/system.jl b/test/system.jl index 8417365..22bdf64 100644 --- a/test/system.jl +++ b/test/system.jl @@ -9,12 +9,16 @@ ids=gen_ids, datetimes=datetimes ) fake_bool_ts = KeyedArray(rand(Bool, 10, 24); ids=gen_ids, datetimes=datetimes) + fake_services_ts = KeyedArray( + vcat(rand(9, 24), fill(missing, 24)'); + ids=gen_ids, datetimes=datetimes + ) branch_names = string.([1, 2, 3]) bus_names = ["A", "B", "C"] @testset "Zone" begin - zone1 = Zone(1, 1.0, 1.0, 1.0, 1.0) + zone1 = Zone(1, 1.0, 1.0, 1.0) @test zone1 isa Zone end @@ -34,9 +38,9 @@ end @testset "System" begin - zone1 = Zone(1, 1.0, 1.0, 1.0, 1.0) - zone2 = Zone(2, 4.0, 2.0, 4.0, 2.0) - zone_market = Zone(-9999, 3.0, 3.0, 3.0, 3.0) + zone1 = Zone(1, 1.0, 1.0, 1.0) + zone2 = Zone(2, 4.0, 2.0, 4.0) + zone_market = Zone(-9999, 3.0, 3.0, 3.0) zones = Dictionary([1, 2, -9999], [zone1, zone2, zone_market]) gen_types = map(gen_ids) do id @@ -64,11 +68,11 @@ psds_per_bus = Dictionary(bus_names, string.(rand('A':'Z', 3)) for _ in bus_names) loads_per_bus = Dictionary(bus_names, string.(rand('A':'Z', 3)) for _ in bus_names) - LODF = Dictionary( + lodf = Dictionary( ["CONTIN_1"], [KeyedArray(rand(3, 1); branches=branch_names, branch=[first(branch_names)])] ) - PTDF = KeyedArray(rand(3, 3); row=branch_names, col=bus_names) + ptdf = KeyedArray(rand(3, 3); row=branch_names, col=bus_names) generator_time_series = GeneratorTimeSeries( fake_vec_ts, @@ -77,10 +81,10 @@ fake_gen_ts, fake_gen_ts, fake_gen_ts, - fake_gen_ts, - fake_gen_ts, - fake_gen_ts, - fake_gen_ts + fake_services_ts, + fake_services_ts, + fake_services_ts, + fake_services_ts ) da_gen_status = GeneratorStatusDA(fake_vec_ts, fake_bool_ts, fake_bool_ts) da_system = SystemDA( @@ -93,8 +97,8 @@ buses, gens, branches, - LODF, - PTDF, + lodf, + ptdf, generator_time_series, da_gen_status, fake_gen_ts, @@ -102,17 +106,7 @@ fake_offer_ts, fake_offer_ts ) - @test da_system isa SystemDA - @test get_datetimes(da_system) == datetimes - - expected_gens_zones = Dict(1 => gen_ids) - @test gens_per_zone(da_system) == expected_gens_zones - - zero_bp, one_bp, two_bp = branches_by_breakpoints(da_system) - @test zero_bp == ["3"] - @test one_bp == String[] #unmonitored - @test two_bp == ["1"] rt_gen_status = GeneratorStatusRT(fake_bool_ts, fake_bool_ts) rt_system = SystemRT( @@ -122,14 +116,76 @@ buses, gens, branches, - LODF, - PTDF, + lodf, + ptdf, generator_time_series, rt_gen_status, fake_gen_ts ) - @test rt_system isa SystemRT - @test get_datetimes(rt_system) == datetimes + + @testset "System accessor functions" begin + @testset "Common accessors $T" for (system, T) in ( + (da_system, SystemDA), (rt_system, SystemRT) + ) + @test get_datetimes(system) == datetimes + @test get_zones(system) == zones + @test get_regulation_requirements(system) == Dictionary([1, 2, -9999], [1.0, 4.0, 3.0]) + @test get_operating_reserve_requirements(system) == Dictionary([1, 2, -9999], [1.0, 2.0, 3.0]) + @test get_good_utility_requirements(system) == Dictionary([1, 2, -9999], [1.0, 4.0, 3.0]) + @test get_buses(system) == buses + @test get_generators(system) == gens + @test get_branches(system) == branches + + @test get_gens_per_bus(system) == gens_per_bus + @test get_loads_per_bus(system) == loads_per_bus + + @test get_ptdf(system) == ptdf + @test get_lodf(system) == lodf + + @test get_initial_generation(system) == fake_vec_ts + @test get_load(system) == fake_gen_ts + @test get_offer_curve(system) == fake_offer_ts + @test get_pmin(system) == fake_gen_ts + @test get_pmax(system) == fake_gen_ts + @test get_regmin(system) == fake_gen_ts + @test get_regmax(system) == fake_gen_ts + + @test skipmissing(get_regulation(system)) == skipmissing(fake_services_ts) + @test skipmissing(get_spinning(system)) == skipmissing(fake_services_ts) + @test skipmissing(get_supplemental_on(system)) == skipmissing(fake_services_ts) + @test skipmissing(get_supplemental_off(system)) == skipmissing(fake_services_ts) + + gens_by_zone = gens_per_zone(da_system) + @test issetequal(keys(gens_by_zone), [1, FullNetworkSystems.MARKET_WIDE_ZONE]) + for (_, v) in gens_by_zone + @test v == gen_ids + end + + zero_bp, one_bp, two_bp = branches_by_breakpoints(da_system) + @test zero_bp == ["3"] + @test one_bp == String[] #unmonitored + @test two_bp == ["1"] + end + + @testset "SystemDA only accessors" begin + @test get_initial_commitment(da_system) isa KeyedArray{Bool, 1} + @test get_incs_per_bus(da_system) == incs_per_bus + @test get_decs_per_bus(da_system) == decs_per_bus + @test get_psds_per_bus(da_system) == psds_per_bus + + @test get_bids(da_system, :increment) == fake_offer_ts + @test get_bids(da_system, :decrement) == fake_offer_ts + @test get_bids(da_system, :price_sensitive_demand) == fake_offer_ts + + @test get_availability(da_system) == fake_bool_ts + @test get_must_run(da_system) == fake_bool_ts + end + + @testset "SystemRT only accessors" begin + @test get_commitment(rt_system) == fake_bool_ts + @test get_regulation_commitment(rt_system) == fake_bool_ts + end + end end end