diff --git a/src/common_models/add_param_container.jl b/src/common_models/add_param_container.jl index d9132799..088b4d89 100644 --- a/src/common_models/add_param_container.jl +++ b/src/common_models/add_param_container.jl @@ -101,8 +101,8 @@ function add_variable_value_parameter_container!( end """ -Allocate an event parameter container (`EventParametersAttributes`). `V` is the component type -whose instances the event affects. +Allocate an event parameter container (`EventParametersAttributes`). `U` is the component type +the event affects; `V` is the supplemental-attribute type describing the event itself. """ function add_event_parameter_container!( container::OptimizationContainer, @@ -115,7 +115,7 @@ function add_event_parameter_container!( ) where { T <: EventParameter, U <: IS.InfrastructureSystemsComponent, - V <: IS.InfrastructureSystemsComponent, + V <: IS.SupplementalAttribute, } param_key = ParameterKey(T, U, meta) attributes = EventParametersAttributes(V, T) diff --git a/src/common_models/add_param_container_shims.jl b/src/common_models/add_param_container_shims.jl index bb3aae22..573b1fc8 100644 --- a/src/common_models/add_param_container_shims.jl +++ b/src/common_models/add_param_container_shims.jl @@ -86,6 +86,6 @@ add_param_container!( ) where { T <: EventParameter, U <: IS.InfrastructureSystemsComponent, - V <: IS.InfrastructureSystemsComponent, + V <: IS.SupplementalAttribute, } = add_event_parameter_container!( container, T, U, V, axs...; sparse = sparse, meta = meta) diff --git a/src/core/parameter_container.jl b/src/core/parameter_container.jl index 07de9837..9b23ce3a 100644 --- a/src/core/parameter_container.jl +++ b/src/core/parameter_container.jl @@ -81,25 +81,30 @@ get_variable_types(attr::CostFunctionAttributes) = attr.variable_types get_uses_compact_power(attr::CostFunctionAttributes) = attr.uses_compact_power struct EventParametersAttributes{ - T <: IS.InfrastructureSystemsComponent, + T <: IS.SupplementalAttribute, U <: ParameterType, } <: ParameterAttributes - affected_devices::Vector{T} end function EventParametersAttributes( ::Type{T}, ::Type{U}, -) where {T <: IS.InfrastructureSystemsComponent, U <: ParameterType} - return EventParametersAttributes{T, U}(T[]) +) where {T <: IS.SupplementalAttribute, U <: ParameterType} + return EventParametersAttributes{T, U}() end function get_param_type( ::EventParametersAttributes{T, U}, -) where {T <: IS.InfrastructureSystemsComponent, U <: ParameterType} +) where {T <: IS.SupplementalAttribute, U <: ParameterType} return U end +function get_attribute_type( + ::EventParametersAttributes{T, U}, +) where {T <: IS.SupplementalAttribute, U <: ParameterType} + return T +end + ################################################################################# # Parameter Container - holds parameter arrays and their attributes ################################################################################# diff --git a/test/InfrastructureOptimizationModelsTests.jl b/test/InfrastructureOptimizationModelsTests.jl index 3f6559e8..ad28b334 100644 --- a/test/InfrastructureOptimizationModelsTests.jl +++ b/test/InfrastructureOptimizationModelsTests.jl @@ -111,7 +111,7 @@ function run_tests() # optimization_problem_outputs_export.jl: low-complexity include(joinpath(TEST_DIR, "test_optimization_outputs.jl")) include(joinpath(TEST_DIR, "test_optimizer_stats.jl")) - # parameter_container.jl: low-complexity + include(joinpath(TEST_DIR, "test_event_parameter_container.jl")) # TODO outputs_by_time.jl # TODO service_model.jl include(joinpath(TEST_DIR, "test_settings.jl")) diff --git a/test/mocks/mock_components.jl b/test/mocks/mock_components.jl index d54f9310..57d7d672 100644 --- a/test/mocks/mock_components.jl +++ b/test/mocks/mock_components.jl @@ -146,6 +146,11 @@ get_from_bus(b::MockBranch) = b.from_bus get_to_bus(b::MockBranch) = b.to_bus get_rate(b::MockBranch) = b.rating +# Mock supplemental attribute type for use as the event type parameter of event +# parameter containers. Real event types (e.g. PSY.FixedForcedOutage) are supplemental +# attributes, not components. +struct MockOutageAttribute <: IS.SupplementalAttribute end + # Mock component type for use as type parameter in container keys # This replaces PSY.ThermalStandard etc. in tests that don't need real PSY types # Subtypes IS.InfrastructureSystemsComponent so it works with VariableKey, ConstraintKey, etc. diff --git a/test/test_event_parameter_container.jl b/test/test_event_parameter_container.jl new file mode 100644 index 00000000..e8dac035 --- /dev/null +++ b/test/test_event_parameter_container.jl @@ -0,0 +1,70 @@ +""" +Unit tests for the event parameter container (`EventParametersAttributes`). + +The type parameter describing the event is a *supplemental attribute*, not a component: +downstream event models key parameters off types such as `PSY.FixedForcedOutage`, which +subtype `IS.SupplementalAttribute`. Bounding that slot on `IS.InfrastructureSystemsComponent` +makes every real call a `MethodError`, so the bound is what these tests pin down. +""" + +struct EventContainerParameter <: IOM.EventParameter end + +function _make_event_parameter_container(time_steps) + mock_sys = MockSystem(100.0) + settings = IOM.Settings( + mock_sys; + horizon = Dates.Hour(length(time_steps)), + resolution = Dates.Hour(1), + time_series_cache_size = 0, + ) + container = IOM.OptimizationContainer(mock_sys, settings, nothing, MockDeterministic) + IOM.set_time_steps!(container, time_steps) + return container +end + +@testset "Event parameter container" begin + time_steps = 1:3 + names = ["A", "B"] + + @testset "Allocation with a supplemental-attribute event type" begin + container = _make_event_parameter_container(time_steps) + param_container = IOM.add_event_parameter_container!( + container, + EventContainerParameter, + MockThermalGen, + MockOutageAttribute, + names, + time_steps, + ) + param_array = IOM.get_parameter_array(param_container) + @test axes(param_array)[1] == names + @test axes(param_array)[2] == time_steps + @test size(IOM.get_multiplier_array(param_container)) == (2, 3) + + attributes = IOM.get_attributes(param_container) + @test attributes isa + IOM.EventParametersAttributes{MockOutageAttribute, EventContainerParameter} + @test IOM.get_param_type(attributes) === EventContainerParameter + @test IOM.get_attribute_type(attributes) === MockOutageAttribute + + @test IOM.has_container_key( + container, + EventContainerParameter, + MockThermalGen, + ) + end + + @testset "The add_param_container! shim routes to the event overload" begin + container = _make_event_parameter_container(time_steps) + param_container = IOM.add_param_container!( + container, + EventContainerParameter, + MockThermalGen, + MockOutageAttribute, + names, + time_steps, + ) + @test IOM.get_attributes(param_container) isa + IOM.EventParametersAttributes{MockOutageAttribute, EventContainerParameter} + end +end diff --git a/test/test_parameterized_range_constraints.jl b/test/test_parameterized_range_constraints.jl index 92d9cf0a..0be0522f 100644 --- a/test/test_parameterized_range_constraints.jl +++ b/test/test_parameterized_range_constraints.jl @@ -183,7 +183,7 @@ end container, TestEventParameter, MockThermalGen, - MockThermalGen, + MockOutageAttribute, names, time_steps, )