From 9e4de699caa6eec9ecdc098cc1d11d18c03da22a Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 12:10:13 -0600 Subject: [PATCH 01/11] change file name to avoid confussion --- src/PowerSimulations.jl | 2 +- .../devices/{interfaces.jl => default_interface_methods.jl} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/devices_models/devices/{interfaces.jl => default_interface_methods.jl} (100%) diff --git a/src/PowerSimulations.jl b/src/PowerSimulations.jl index 0a36addcd9..cd8544a63c 100644 --- a/src/PowerSimulations.jl +++ b/src/PowerSimulations.jl @@ -556,7 +556,7 @@ include("devices_models/devices/common/duration_constraints.jl") include("devices_models/devices/common/get_time_series.jl") # Device Modeling components -include("devices_models/devices/interfaces.jl") +include("devices_models/devices/default_interface_methods.jl") include("devices_models/devices/common/add_to_expression.jl") include("devices_models/devices/common/set_expression.jl") include("devices_models/devices/renewable_generation.jl") diff --git a/src/devices_models/devices/interfaces.jl b/src/devices_models/devices/default_interface_methods.jl similarity index 100% rename from src/devices_models/devices/interfaces.jl rename to src/devices_models/devices/default_interface_methods.jl From 2e4b706caf475a38e313fd2f7513f8fce593c20e Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 14:09:03 -0600 Subject: [PATCH 02/11] add ts parameter calls in constructor --- .../thermalgeneration_constructor.jl | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/src/devices_models/device_constructors/thermalgeneration_constructor.jl b/src/devices_models/device_constructors/thermalgeneration_constructor.jl index 5225586c43..3c6f50c09c 100644 --- a/src/devices_models/device_constructors/thermalgeneration_constructor.jl +++ b/src/devices_models/device_constructors/thermalgeneration_constructor.jl @@ -56,6 +56,10 @@ function construct_device!( initial_conditions!(container, devices, D()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -135,6 +139,17 @@ function construct_device!( add_constraints!(container, RampConstraint, devices, model, network_model) add_constraints!(container, DurationConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end + add_feedforward_constraints!(container, model, devices) objective_function!(container, devices, model, get_network_formulation(network_model)) @@ -164,6 +179,10 @@ function construct_device!( initial_conditions!(container, devices, D()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -227,6 +246,16 @@ function construct_device!( add_constraints!(container, CommitmentConstraint, devices, model, network_model) add_constraints!(container, RampConstraint, devices, model, network_model) add_constraints!(container, DurationConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end add_feedforward_constraints!(container, model, devices) @@ -256,6 +285,10 @@ function construct_device!( initial_conditions!(container, devices, ThermalBasicUnitCommitment()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -335,6 +368,17 @@ function construct_device!( ) add_constraints!(container, CommitmentConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end + add_feedforward_constraints!(container, model, devices) objective_function!(container, devices, model, get_network_formulation(network_model)) @@ -361,6 +405,10 @@ function construct_device!( initial_conditions!(container, devices, ThermalBasicUnitCommitment()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -423,6 +471,16 @@ function construct_device!( ) add_constraints!(container, CommitmentConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end add_feedforward_constraints!(container, model, devices) @@ -829,6 +887,10 @@ function construct_device!( initial_conditions!(container, devices, ThermalMultiStartUnitCommitment()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -931,6 +993,16 @@ function construct_device!( network_model, ) add_constraints!(container, ActiveRangeICConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end add_feedforward_constraints!(container, model, devices) @@ -965,6 +1037,10 @@ function construct_device!( add_variables!(container, TimeDurationOff, devices, ThermalMultiStartUnitCommitment()) add_variables!(container, PowerOutput, devices, ThermalMultiStartUnitCommitment()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -1053,6 +1129,16 @@ function construct_device!( network_model, ) add_constraints!(container, ActiveRangeICConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end add_feedforward_constraints!(container, model, devices) @@ -1092,6 +1178,10 @@ function construct_device!( initial_conditions!(container, devices, ThermalCompactUnitCommitment()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -1169,6 +1259,16 @@ function construct_device!( add_constraints!(container, CommitmentConstraint, devices, model, network_model) add_constraints!(container, RampConstraint, devices, model, network_model) add_constraints!(container, DurationConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end add_feedforward_constraints!(container, model, devices) @@ -1202,6 +1302,10 @@ function construct_device!( initial_conditions!(container, devices, ThermalCompactUnitCommitment()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -1270,6 +1374,16 @@ function construct_device!( add_constraints!(container, CommitmentConstraint, devices, model, network_model) add_constraints!(container, RampConstraint, devices, model, network_model) add_constraints!(container, DurationConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end add_feedforward_constraints!(container, model, devices) @@ -1307,6 +1421,10 @@ function construct_device!( initial_conditions!(container, devices, ThermalBasicCompactUnitCommitment()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -1382,6 +1500,16 @@ function construct_device!( network_model, ) add_constraints!(container, CommitmentConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end add_feedforward_constraints!(container, model, devices) @@ -1413,6 +1541,10 @@ function construct_device!( initial_conditions!(container, devices, ThermalBasicCompactUnitCommitment()) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_parameters!(container, ActivePowerTimeSeriesParameter, devices, model) + end + add_to_expression!( container, ActivePowerBalance, @@ -1479,6 +1611,16 @@ function construct_device!( ) add_constraints!(container, CommitmentConstraint, devices, model, network_model) + if haskey(get_time_series_names(model), ActivePowerTimeSeriesParameter) + add_constraints!( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + ActivePowerRangeExpressionUB, + devices, + model, + network_model, + ) + end add_feedforward_constraints!(container, model, devices) From 94e0ec345f14f3a2ba5f9349355ca75f3a385518 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 14:09:24 -0600 Subject: [PATCH 03/11] add constraint call --- .../devices/thermal_generation.jl | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/devices_models/devices/thermal_generation.jl b/src/devices_models/devices/thermal_generation.jl index 66809d18dc..3b47c0ed35 100644 --- a/src/devices_models/devices/thermal_generation.jl +++ b/src/devices_models/devices/thermal_generation.jl @@ -442,6 +442,30 @@ function _get_data_for_range_ic( return ini_conds end +function add_constraints!( + container::OptimizationContainer, + ::Type{ActivePowerVariableTimeSeriesLimitsConstraint}, + U::Type{<:Union{ActivePowerVariable, ActivePowerRangeExpressionUB}}, + devices::IS.FlattenIteratorWrapper{V}, + model::DeviceModel{V, W}, + ::NetworkModel{X}, +) where { + V <: PSY.ThermalGen, + W <: AbstractThermalUnitCommitment, + X <: PM.AbstractPowerModel, +} + add_parameterized_upper_bound_range_constraints( + container, + ActivePowerVariableTimeSeriesLimitsConstraint, + U, + ActivePowerTimeSeriesParameter, + devices, + model, + X, + ) + return +end + """ This function adds range constraint for the first time period. Constraint (10) from PGLIB formulation """ From d35233dcec1292d53563f25698deddfa7353bb35 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 14:09:37 -0600 Subject: [PATCH 04/11] add checks for ts property --- .../devices/common/range_constraint.jl | 19 ++++++++++++++++--- src/parameters/add_parameters.jl | 3 +++ src/services_models/services_constructor.jl | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/devices_models/devices/common/range_constraint.jl b/src/devices_models/devices/common/range_constraint.jl index 0a7c4b804c..37e5495caa 100644 --- a/src/devices_models/devices/common/range_constraint.jl +++ b/src/devices_models/devices/common/range_constraint.jl @@ -706,6 +706,9 @@ function lower_bound_range_with_parameter!( jump_model = get_jump_model(container) time_steps = axes(constraint_container)[2] for device in devices + if !(PSY.has_time_series(device)) + continue + end name = PSY.get_name(device) param = get_parameter_column_refs(param_container, name) for t in time_steps @@ -730,8 +733,11 @@ function _add_parameterized_lower_bound_range_constraints_impl!( W <: AbstractDeviceFormulation, } time_steps = get_time_steps(container) - names = [PSY.get_name(d) for d in devices] - + names = [PSY.get_name(d) for d in devices if PSY.has_time_series(d)] + if isempty(names) + @debug "There are no $V devices with time series data" + return + end constraint = add_constraints_container!(container, T(), V, names, time_steps; meta = "lb") @@ -842,6 +848,9 @@ function upper_bound_range_with_parameter!( time_steps = axes(constraint_container)[2] for device in devices name = PSY.get_name(device) + if !(PSY.has_time_series(device)) + continue + end param = get_parameter_column_refs(param_container, name) for t in time_steps constraint_container[name, t] = @@ -865,7 +874,11 @@ function _add_parameterized_upper_bound_range_constraints_impl!( W <: AbstractDeviceFormulation, } time_steps = get_time_steps(container) - names = [PSY.get_name(d) for d in devices] + names = [PSY.get_name(d) for d in devices if PSY.has_time_series(d)] + if isempty(names) + @debug "There are no $V devices with time series data" + return + end constraint = add_constraints_container!(container, T(), V, names, time_steps; meta = "ub") diff --git a/src/parameters/add_parameters.jl b/src/parameters/add_parameters.jl index 76f1ef2095..127e3d8464 100644 --- a/src/parameters/add_parameters.jl +++ b/src/parameters/add_parameters.jl @@ -197,6 +197,9 @@ function _add_time_series_parameters!( device_names = String[] initial_values = Dict{String, AbstractArray}() for device in devices + if !PSY.has_time_series(device) + continue + end push!(device_names, PSY.get_name(device)) ts_uuid = string(IS.get_time_series_uuid(ts_type, device, ts_name)) if !(ts_uuid in keys(initial_values)) diff --git a/src/services_models/services_constructor.jl b/src/services_models/services_constructor.jl index 6deb80d300..8b02409f05 100644 --- a/src/services_models/services_constructor.jl +++ b/src/services_models/services_constructor.jl @@ -548,7 +548,7 @@ function construct_service!( PSY.get_name.(interfaces), get_time_steps(container), ) - #add_feedforward_arguments!(container, model, service) + add_feedforward_arguments!(container, model, service) return end From c1231d62c903d48ac3813047c321ee8e86b0d257 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 14:58:25 -0600 Subject: [PATCH 05/11] improve error print --- src/devices_models/devices/default_interface_methods.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices_models/devices/default_interface_methods.jl b/src/devices_models/devices/default_interface_methods.jl index 0fd71e6243..5391344ae7 100644 --- a/src/devices_models/devices/default_interface_methods.jl +++ b/src/devices_models/devices/default_interface_methods.jl @@ -11,7 +11,7 @@ get_variable_lower_bound(_, ::PSY.Component, __) = nothing get_variable_upper_bound(_, ::PSY.Component, __) = nothing get_multiplier_value(x, y::PSY.Component, z) = - error("Unable to get parameter $x for device $y for formulation $z") + error("Unable to get parameter $x for device $(IS.summary(y)) for formulation $z") get_expression_type_for_reserve(_, y::Type{<:PSY.Component}, z) = error("`get_expression_type_for_reserve` must be implemented for $y and $z") From a9e29661f61764c0e632a9e8c883ad7d6dce003e Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 14:58:37 -0600 Subject: [PATCH 06/11] add multiplier function --- src/devices_models/devices/thermal_generation.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/devices_models/devices/thermal_generation.jl b/src/devices_models/devices/thermal_generation.jl index 3b47c0ed35..536d54eadf 100644 --- a/src/devices_models/devices/thermal_generation.jl +++ b/src/devices_models/devices/thermal_generation.jl @@ -50,6 +50,7 @@ get_variable_upper_bound(::StartVariable, d::PSY.ThermalGen, ::AbstractThermalFo get_variable_binary(::Union{ColdStartVariable, WarmStartVariable, HotStartVariable}, ::Type{PSY.ThermalMultiStart}, ::AbstractThermalFormulation) = true ########################### Parameter related set functions ################################ +get_multiplier_value(::ActivePowerTimeSeriesParameter, d::PSY.ThermalGen, ::AbstractThermalFormulation) = PSY.get_max_active_power(d) get_parameter_multiplier(::VariableValueParameter, d::PSY.ThermalGen, ::AbstractThermalFormulation) = 1.0 get_initial_parameter_value(::VariableValueParameter, d::PSY.ThermalGen, ::AbstractThermalFormulation) = 1.0 get_expression_multiplier(::OnStatusParameter, ::ActivePowerRangeExpressionUB, d::PSY.ThermalGen, ::AbstractThermalFormulation) = PSY.get_active_power_limits(d).max From 1a5774f71bf4a92258825050ea10e0ff968a4dfa Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 14:58:45 -0600 Subject: [PATCH 07/11] another time series check --- src/parameters/add_parameters.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/parameters/add_parameters.jl b/src/parameters/add_parameters.jl index 127e3d8464..ae39d01d4f 100644 --- a/src/parameters/add_parameters.jl +++ b/src/parameters/add_parameters.jl @@ -229,6 +229,9 @@ function _add_time_series_parameters!( end for device in devices + if !PSY.has_time_series(device) + continue + end name = PSY.get_name(device) multiplier = get_multiplier_value(T(), device, W()) for step in time_steps From e47f4e663e9caae20dedcd5990059cf3acb62307 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 14:58:55 -0600 Subject: [PATCH 08/11] add constructor test --- ..._device_thermal_generation_constructors.jl | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/test_device_thermal_generation_constructors.jl b/test/test_device_thermal_generation_constructors.jl index cdb3a38813..9197bcd5e4 100644 --- a/test/test_device_thermal_generation_constructors.jl +++ b/test/test_device_thermal_generation_constructors.jl @@ -921,3 +921,49 @@ end end end end + +@testset "Thermal with max_active_power time series" begin + device_model = DeviceModel( + ThermalStandard, + ThermalStandardUnitCommitment; + time_series_names = Dict(ActivePowerTimeSeriesParameter => "max_active_power")) + c_sys5 = PSB.build_system(PSITestSystems, "c_sys5") + + derate_data = SortedDict{Dates.DateTime, TimeSeries.TimeArray}() + data_ts = collect( + DateTime("1/1/2024 0:00:00", "d/m/y H:M:S"):Hour(1):DateTime( + "1/1/2024 23:00:00", + "d/m/y H:M:S", + ), + ) + for t in 1:2 + ini_time = data_ts[1] + Day(t - 1) + derate_data[ini_time] = + TimeArray(data_ts + Day(t - 1), fill!(Vector{Float64}(undef, 24), 0.8)) + end + solitude = get_component(ThermalStandard, c_sys5, "Solitude") + PSY.add_time_series!( + c_sys5, + solitude, + PSY.Deterministic("max_active_power", derate_data), + ) + + model = DecisionModel( + MockOperationProblem, + DCPPowerModel, + c_sys5) + + mock_construct_device!(model, device_model) + moi_tests(model, 480, 0, 504, 120, 120, true) + key = PSI.ConstraintKey( + ActivePowerVariableTimeSeriesLimitsConstraint, + ThermalStandard, + "ub", + ) + constraint = PSI.get_constraint(PSI.get_optimization_container(model), key) + ub_value = get_max_active_power(solitude) * 0.8 + for ix in eachindex(constraint) + @test JuMP.normalized_rhs(constraint[ix]) == ub_value + end + psi_checkobjfun_test(model, GAEVF) +end From 21251179077f4ab696974ee226a4d0ef024511c6 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 15:00:43 -0600 Subject: [PATCH 09/11] fix test --- src/services_models/services_constructor.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services_models/services_constructor.jl b/src/services_models/services_constructor.jl index 8b02409f05..e645c2cf82 100644 --- a/src/services_models/services_constructor.jl +++ b/src/services_models/services_constructor.jl @@ -534,9 +534,9 @@ function construct_service!( network_model::NetworkModel{<:PM.AbstractPowerModel}, ) where {T <: PSY.TransmissionInterface} interfaces = get_available_components(model, sys) + interface = PSY.get_component(T, sys, get_service_name(model)) if get_use_slacks(model) # Adding the slacks can be done in a cleaner fashion - interface = PSY.get_component(T, sys, get_service_name(model)) @assert PSY.get_available(interface) transmission_interface_slacks!(container, interface) end @@ -548,7 +548,7 @@ function construct_service!( PSY.get_name.(interfaces), get_time_steps(container), ) - add_feedforward_arguments!(container, model, service) + add_feedforward_arguments!(container, model, interface) return end From 444afb208d85d4aa2b894b3047ce8f4bdcf0fcd6 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 15:52:39 -0600 Subject: [PATCH 10/11] comment out unrelated broken method --- src/services_models/services_constructor.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services_models/services_constructor.jl b/src/services_models/services_constructor.jl index e645c2cf82..f547d622b3 100644 --- a/src/services_models/services_constructor.jl +++ b/src/services_models/services_constructor.jl @@ -548,7 +548,8 @@ function construct_service!( PSY.get_name.(interfaces), get_time_steps(container), ) - add_feedforward_arguments!(container, model, interface) + # TODO:broken + # add_feedforward_arguments!(container, model, interface) return end From fc6fc9636902c9f84082f334db0d84d60e610e13 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 13 Oct 2024 17:55:41 -0600 Subject: [PATCH 11/11] add missing ts check --- src/parameters/update_container_parameter_values.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/parameters/update_container_parameter_values.jl b/src/parameters/update_container_parameter_values.jl index 5784c0964f..be42d2b006 100644 --- a/src/parameters/update_container_parameter_values.jl +++ b/src/parameters/update_container_parameter_values.jl @@ -50,6 +50,9 @@ function _update_parameter_values!( components = get_available_components(device_model, get_system(model)) ts_uuids = Set{String}() for component in components + if !PSY.has_time_series(component) + continue + end ts_uuid = string(IS.get_time_series_uuid(U, component, ts_name)) if !(ts_uuid in ts_uuids) ts_vector = get_time_series_values!(