Skip to content

Commit

Permalink
Merge pull request #1120 from NREL-Sienna/rh/add_ts_to_interchange
Browse files Browse the repository at this point in the history
Add ts to interchange
  • Loading branch information
jd-lara committed Jul 3, 2024
2 parents 511b067 + 5cef076 commit 8be4a70
Show file tree
Hide file tree
Showing 12 changed files with 476 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/PowerSimulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export NonSpinningReserve
export PIDSmoothACE
export GroupReserve
export ConstantMaxInterfaceFlow
export VariableMaxInterfaceFlow

######## Branch Models ########
export StaticBranch
Expand Down
4 changes: 4 additions & 0 deletions src/core/formulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,7 @@ struct NonSpinningReserve <: AbstractReservesFormulation end
Struct to add a constant maximum transmission flow for specified interface
"""
struct ConstantMaxInterfaceFlow <: AbstractServiceFormulation end
"""
Struct to add a variable maximum transmission flow for specified interface
"""
struct VariableMaxInterfaceFlow <: AbstractServiceFormulation end
22 changes: 21 additions & 1 deletion src/core/parameters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,30 @@ Parameter to define reactive power time series
struct ReactivePowerTimeSeriesParameter <: TimeSeriesParameter end

"""
Paramter to define requirement time series
Parameter to define requirement time series
"""
struct RequirementTimeSeriesParameter <: TimeSeriesParameter end

"""
Parameter to define Flow From_To limit time series
"""
struct FromToFlowLimitParameter <: TimeSeriesParameter end

"""
Parameter to define Flow To_From limit time series
"""
struct ToFromFlowLimitParameter <: TimeSeriesParameter end

"""
Parameter to define Max Flow limit for interface time series
"""
struct MaxInterfaceFlowLimitParameter <: TimeSeriesParameter end

"""
Parameter to define Min Flow limit for interface time series
"""
struct MinInterfaceFlowLimitParameter <: TimeSeriesParameter end

abstract type VariableValueParameter <: RightHandSideParameter end

"""
Expand Down
19 changes: 19 additions & 0 deletions src/devices_models/device_constructors/branch_constructor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,12 @@ function construct_device!(
)
end
devices = get_available_components(model, sys)
has_ts = PSY.has_time_series.(devices)
if any(has_ts) && !all(has_ts)
error(
"Not all AreaInterchange devices have time series. Check data to complete (or remove) time series.",
)
end
add_variables!(
container,
FlowActivePowerVariable,
Expand All @@ -915,6 +921,19 @@ function construct_device!(
model,
network_model,
)
if all(has_ts)
for device in devices
name = PSY.get_name(device)
num_ts = length(unique(PSY.get_name.(PSY.get_time_series_keys(device))))
if num_ts < 2
error(
"AreaInterchange $name has less than two time series. It is required to add both from_to and to_from time series.",
)
end
end
add_parameters!(container, FromToFlowLimitParameter, devices, model)
add_parameters!(container, ToFromFlowLimitParameter, devices, model)
end
return
end

Expand Down
72 changes: 57 additions & 15 deletions src/devices_models/devices/area_interchange.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
#! format: off
get_multiplier_value(::FromToFlowLimitParameter, d::PSY.AreaInterchange, ::AbstractBranchFormulation) = -1.0 * PSY.get_from_to_flow_limit(d)
get_multiplier_value(::ToFromFlowLimitParameter, d::PSY.AreaInterchange, ::AbstractBranchFormulation) = PSY.get_to_from_flow_limit(d)
#! format: on

function get_default_time_series_names(
::Type{PSY.AreaInterchange},
::Type{V},
) where {V <: AbstractBranchFormulation}
return Dict{Type{<:TimeSeriesParameter}, String}()
return Dict{Type{<:TimeSeriesParameter}, String}(
FromToFlowLimitParameter => "from_to_flow_limit",
ToFromFlowLimitParameter => "to_from_flow_limit",
)
end

function get_default_attributes(
Expand Down Expand Up @@ -71,22 +79,56 @@ function add_constraints!(
)

var_array = get_variable(container, FlowActivePowerVariable(), PSY.AreaInterchange)

for device in devices
ci_name = PSY.get_name(device)
to_from_limit = PSY.get_flow_limits(device).to_from
from_to_limit = PSY.get_flow_limits(device).from_to
for t in time_steps
con_lb[ci_name, t] =
JuMP.@constraint(
get_jump_model(container),
var_array[ci_name, t] >= -1.0 * from_to_limit
if !all(PSY.has_time_series.(devices))
for device in devices
ci_name = PSY.get_name(device)
to_from_limit = PSY.get_flow_limits(device).to_from
from_to_limit = PSY.get_flow_limits(device).from_to
for t in time_steps
con_lb[ci_name, t] =
JuMP.@constraint(
get_jump_model(container),
var_array[ci_name, t] >= -1.0 * from_to_limit
)
con_ub[ci_name, t] =
JuMP.@constraint(
get_jump_model(container),
var_array[ci_name, t] <= to_from_limit
)
end
end
else
param_container_from_to =
get_parameter(container, FromToFlowLimitParameter(), PSY.AreaInterchange)
param_multiplier_from_to = get_parameter_multiplier_array(
container,
FromToFlowLimitParameter(),
PSY.AreaInterchange,
)
param_container_to_from =
get_parameter(container, ToFromFlowLimitParameter(), PSY.AreaInterchange)
param_multiplier_to_from = get_parameter_multiplier_array(
container,
ToFromFlowLimitParameter(),
PSY.AreaInterchange,
)
jump_model = get_jump_model(container)
for device in devices
name = PSY.get_name(device)
param_from_to = get_parameter_column_refs(param_container_from_to, name)
param_to_from = get_parameter_column_refs(param_container_to_from, name)
for t in time_steps
con_lb[name, t] = JuMP.@constraint(
jump_model,
var_array[name, t] >=
param_multiplier_from_to[name, t] * param_from_to[t]
)
con_ub[ci_name, t] =
JuMP.@constraint(
get_jump_model(container),
var_array[ci_name, t] <= to_from_limit
con_ub[name, t] = JuMP.@constraint(
jump_model,
var_array[name, t] <=
param_multiplier_to_from[name, t] * param_to_from[t]
)
end
end
end
return
Expand Down
4 changes: 2 additions & 2 deletions src/devices_models/devices/common/add_to_expression.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1151,8 +1151,8 @@ function add_to_expression!(
::Type{InterfaceTotalFlow},
::Type{FlowActivePowerVariable},
service::PSY.TransmissionInterface,
model::ServiceModel{PSY.TransmissionInterface, ConstantMaxInterfaceFlow},
)
model::ServiceModel{PSY.TransmissionInterface, V},
) where {V <: Union{ConstantMaxInterfaceFlow, VariableMaxInterfaceFlow}}
expression = get_expression(container, InterfaceTotalFlow(), PSY.TransmissionInterface)
service_name = get_service_name(model)
for (device_type, devices) in get_contributing_devices_map(model)
Expand Down
8 changes: 8 additions & 0 deletions src/operation/problem_template.jl
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,14 @@ function _modify_device_model!(
return
end

function _modify_device_model!(
::Dict{Symbol, DeviceModel},
::ServiceModel{PSY.TransmissionInterface, VariableMaxInterfaceFlow},
::Vector,
)
return
end

function _add_services_to_device_model!(template::ProblemTemplate)
service_models = get_service_models(template)
devices_template = get_device_models(template)
Expand Down
4 changes: 2 additions & 2 deletions src/parameters/add_parameters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function add_parameters!(
::Type{T},
service::U,
model::ServiceModel{U, V},
) where {T <: TimeSeriesParameter, U <: PSY.Service, V <: AbstractReservesFormulation}
) where {T <: TimeSeriesParameter, U <: PSY.Service, V <: AbstractServiceFormulation}
if get_rebuild_model(get_settings(container)) &&
has_container_key(container, T, U, PSY.get_name(service))
return
Expand Down Expand Up @@ -258,7 +258,7 @@ function _add_parameters!(
::T,
service::U,
model::ServiceModel{U, V},
) where {T <: TimeSeriesParameter, U <: PSY.Service, V <: AbstractReservesFormulation}
) where {T <: TimeSeriesParameter, U <: PSY.Service, V <: AbstractServiceFormulation}
ts_type = get_default_time_series_type(container)
if !(ts_type <: Union{PSY.AbstractDeterministic, PSY.StaticTimeSeries})
error("add_parameters! for TimeSeriesParameter is not compatible with $ts_type")
Expand Down
91 changes: 91 additions & 0 deletions src/services_models/services_constructor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,94 @@ function construct_service!(
objective_function!(container, service, model)
return
end

function construct_service!(
container::OptimizationContainer,
sys::PSY.System,
::ArgumentConstructStage,
model::ServiceModel{T, VariableMaxInterfaceFlow},
devices_template::Dict{Symbol, DeviceModel},
incompatible_device_types::Set{<:DataType},
network_model::NetworkModel{<:PM.AbstractPowerModel},
) where {T <: PSY.TransmissionInterface}
interfaces = get_available_components(model, sys)
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
# Lazy container addition for the expressions.
lazy_container_addition!(
container,
InterfaceTotalFlow(),
T,
PSY.get_name.(interfaces),
get_time_steps(container),
)
has_ts = PSY.has_time_series.(interfaces)
if any(has_ts) && !all(has_ts)
error(
"Not all TransmissionInterfaces devices have time series. Check data to complete (or remove) time series.",
)
end
if all(has_ts)
for device in interfaces
name = PSY.get_name(device)
num_ts = length(unique(PSY.get_name.(PSY.get_time_series_keys(device))))
if num_ts < 2
error(
"TransmissionInterface $name has less than two time series. It is required to add both min_flow and max_flow time series.",
)
end
add_parameters!(container, MinInterfaceFlowLimitParameter, device, model)
add_parameters!(container, MaxInterfaceFlowLimitParameter, device, model)
end
end
#add_feedforward_arguments!(container, model, service)
return
end

function construct_service!(
container::OptimizationContainer,
sys::PSY.System,
::ModelConstructStage,
model::ServiceModel{T, VariableMaxInterfaceFlow},
devices_template::Dict{Symbol, DeviceModel},
incompatible_device_types::Set{<:DataType},
network_model::NetworkModel{<:PM.AbstractActivePowerModel},
) where {T <: PSY.TransmissionInterface}
name = get_service_name(model)
service = PSY.get_component(T, sys, name)

add_to_expression!(
container,
InterfaceTotalFlow,
FlowActivePowerVariable,
service,
model,
)

if get_use_slacks(model)
add_to_expression!(
container,
InterfaceTotalFlow,
InterfaceFlowSlackUp,
service,
model,
)
add_to_expression!(
container,
InterfaceTotalFlow,
InterfaceFlowSlackDown,
service,
model,
)
end

add_constraints!(container, InterfaceFlowLimit, service, model)
add_feedforward_constraints!(container, model, service)
add_constraint_dual!(container, sys, model)
objective_function!(container, service, model)
return
end
Loading

0 comments on commit 8be4a70

Please sign in to comment.