Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/operation/problem_template.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,9 @@ function _populate_contributing_devices!(template::ProblemTemplate, sys::PSY.Sys
)
end
if isempty(get_contributing_devices_map(service_model))
error(
"The contributing devices for service $(PSY.get_name(service)) is empty. Add contributing devices to the service in the data to continue.",
)
@warn "The contributing devices for service $(PSY.get_name(service)) is empty, consider removing the service from the system" _group =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ChenHaotianC accept this change. This is correct.

LOG_GROUP_SERVICE_CONSTUCTORS
continue
end
end
return
Expand Down
2 changes: 1 addition & 1 deletion src/services_models/reserves.jl
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ function add_constraints!(
component_type = typeof(d)
name = PSY.get_name(d)
varstatus = get_variable(container, OnVariable(), component_type)
startup_time = PSY.get_time_limits(d).up
startup_time = PSY.get_time_limits(d).down
ramp_limits = _get_ramp_limits(d)
if reserve_response_time > startup_time
Comment on lines 483 to 488

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is somewhat correct. The time_limits(d).up is how much hours the unit needs to be kept on once the OnVariable changes from 0 to 1. It is what is called the minimum start up time time.

In here we are using this as how long it takes to be completely turn on. @jd-lara Is it okay to use these two approaches interchangeably here?

reserve_limit =
Expand Down
52 changes: 28 additions & 24 deletions src/services_models/services_constructor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ function construct_services!(
isempty(services_template) && return
incompatible_device_types = get_incompatible_devices(devices_template)

groupservice = nothing
groupservices = Any[]

for (key, service_model) in services_template
if get_formulation(service_model) === GroupReserve # group service needs to be constructed last
groupservice = key
if get_formulation(service_model) === GroupReserve # group service needs to be constructed last
push!(groupservices, key)
continue
Comment on lines +26 to 31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is okay I guess? @ChenHaotianC You could try to replace with something like:
groupservices = Tuple{String, Symbol}[] and check if its works?

end
isempty(get_contributing_devices(service_model)) && continue
Expand All @@ -41,15 +41,17 @@ function construct_services!(
network_model,
)
end
groupservice === nothing || construct_service!(
container,
sys,
stage,
services_template[groupservice],
devices_template,
incompatible_device_types,
network_model,
)
for key in groupservices
construct_service!(
container,
sys,
stage,
services_template[key],
devices_template,
incompatible_device_types,
network_model,
)
end
return
end

Expand All @@ -64,10 +66,10 @@ function construct_services!(
isempty(services_template) && return
incompatible_device_types = get_incompatible_devices(devices_template)

groupservice = nothing
groupservices = Any[]
for (key, service_model) in services_template
if get_formulation(service_model) === GroupReserve # group service needs to be constructed last
groupservice = key
if get_formulation(service_model) === GroupReserve # group service needs to be constructed last
push!(groupservices, key)
continue
Comment on lines +69 to 73

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

end
isempty(get_contributing_devices_map(service_model)) && continue
Expand All @@ -81,15 +83,17 @@ function construct_services!(
network_model,
)
end
groupservice === nothing || construct_service!(
container,
sys,
stage,
services_template[groupservice],
devices_template,
incompatible_device_types,
network_model,
)
for key in groupservices
construct_service!(
container,
sys,
stage,
services_template[key],
devices_template,
incompatible_device_types,
network_model,
)
end
return
end

Expand Down
83 changes: 83 additions & 0 deletions test/test_services_constructor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1030,3 +1030,86 @@ end
output_dir = mktempdir(; cleanup = true),
) == PSI.ModelBuildStatus.FAILED
end

@testset "Test Multiple GroupReserve Constraints" begin
template = get_thermal_dispatch_template_network()
set_service_model!(
template,
ServiceModel(VariableReserve{ReserveUp}, RangeReserve, "Reserve1"),
)
set_service_model!(
template,
ServiceModel(VariableReserve{ReserveUp}, RangeReserve, "Reserve11"),
)
set_service_model!(
template,
ServiceModel(VariableReserve{ReserveDown}, RangeReserve, "Reserve2"),
)
set_service_model!(
template,
ServiceModel(ReserveDemandCurve{ReserveUp}, StepwiseCostReserve, "ORDC1"),
)

c_sys5_uc = PSB.build_system(PSITestSystems, "c_sys5_uc"; add_reserves = true)
services = get_components(Service, c_sys5_uc)
requirement_group1 = 5.0
contributing_services = Vector{Service}()
for service in services
if (typeof(service) <: PSY.VariableReserve{ReserveUp})
push!(contributing_services, service)
end
end
groupservice = ConstantReserveGroup{ReserveSymmetric}(;
name = "group_reserve_1",
available = true,
requirement = requirement_group1,
ext = Dict{String, Any}(),
)
add_service!(c_sys5_uc, groupservice, contributing_services)

contributing_services = Vector{Service}()
requirement_group2 = 10.0
for service in services
if (typeof(service) <: PSY.VariableReserve{ReserveUp}) || (typeof(service) <: PSY.VariableReserve{ReserveDown})
push!(contributing_services, service)
end
end
groupservice = ConstantReserveGroup{ReserveSymmetric}(;
name = "group_reserve_2",
available = true,
requirement = requirement_group2,
ext = Dict{String, Any}(),
)
add_service!(c_sys5_uc, groupservice, contributing_services)

set_service_model!(
template,
ServiceModel(ConstantReserveGroup{ReserveSymmetric}, GroupReserve),
)

model = DecisionModel(template, c_sys5_uc)
@test build!(model; output_dir = mktempdir(; cleanup = true)) ==
PSI.ModelBuildStatus.BUILT

container = model.internal.container

group_reserve_key1 = PSI.ConstraintKey(
RequirementConstraint,
ConstantReserveGroup{ReserveSymmetric},
"group_reserve_1",
)
cons1 = PSI.get_constraint(container, group_reserve_key1)

group_reserve_key2 = PSI.ConstraintKey(
RequirementConstraint,
ConstantReserveGroup{ReserveSymmetric},
"group_reserve_2",
)
cons2 = PSI.get_constraint(container, group_reserve_key2)

@test all((
all(JuMP.normalized_rhs.(cons1).data .== requirement_group1),
all(JuMP.normalized_rhs.(cons2).data .== requirement_group2),
))

end
Loading