Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed the default number of units based on is_candidate. #1036

Merged
merged 8 commits into from
Nov 26, 2024
2 changes: 1 addition & 1 deletion docs/src/concept_reference/number_of_units.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Defines how many members a certain [unit](@ref) object represents. Typically this parameter takes a binary (UC) or integer (clustered UC) value. Together with the [unit\_availability\_factor](@ref) and [units\_unavailable](@ref), this will determine the maximum number of members that can be online at any given time. (Thus restricting the [units\_on](@ref) variable). It is possible to allow the model to increase the `number_of_units` itself, through [Investment Optimization](@ref). It is also possible to schedule maintenance outages using [outage\_variable\_type](@ref) and [scheduled\_outage\_duration](@ref).

The default value for this parameter is 1.
The default value for this parameter is 1. The default value is 0 when [candidate\_units](@ref) has been defined for the unit in question.
5 changes: 4 additions & 1 deletion src/constraints/constraint_units_available.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ function _build_constraint_units_available(m, u, s, t)
init=0,
)
<=
+ number_of_units(m; unit=u, stochastic_scenario=s, t=t)
# Change the default number of units so that it is zero when candidate units are present
# and otherwise 1.
+ ifelse(is_candidate(unit=u), number_of_units(m; unit=u, stochastic_scenario=s, t=t, _default=0),
number_of_units(m; unit=u, stochastic_scenario=s, t=t) )
- units_unavailable(m; unit=u, stochastic_scenario=s, t=t)
)
end
Expand Down
2 changes: 1 addition & 1 deletion templates/spineopt_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@
["unit", "is_renewable", false, "boolean_value_list", "Whether the unit is renewable - used in the minimum renewable generation constraint within the Benders master problem"],
["unit", "min_down_time", null, null, "Minimum downtime of a `unit` after it shuts down."],
["unit", "min_up_time", null, null, "Minimum uptime of a `unit` after it starts up."],
["unit", "number_of_units", 1.0, null, "Denotes the number of 'sub units' aggregated to form the modelled `unit`."],
["unit", "number_of_units", 1.0, null, "Denotes the number of 'sub units' aggregated to form the modelled `unit`. The default value becomes zero if `candidate_units` has been defined."],
["unit", "online_variable_type", "unit_online_variable_type_linear", "unit_online_variable_type_list", "A selector for how the `units_on` variable is represented within the model."],
["unit", "outage_variable_type", "unit_online_variable_type_none", "unit_online_variable_type_list", "Determines whether the outage variable is integer or continuous or none(no optimisation of maintenance outages)."],
["unit", "scheduled_outage_duration", null, null, "Specifies the amount of time a unit must be out of service for maintenance as a single block over the course of the optimisation window"],
Expand Down
37 changes: 36 additions & 1 deletion test/constraints/constraint_unit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,12 @@ function test_constraint_units_available()
end
end
end

function test_constraint_units_available_units_unavailable()
@testset "constraint_units_available_units_unavailable" begin
url_in = _test_constraint_unit_setup()
number_of_units = 4
candidate_units = 3
candidate_units = 3
units_unavailable = 1
unit_availability_factor = 0.5
object_parameter_values = [
Expand Down Expand Up @@ -191,6 +192,40 @@ function test_constraint_units_available_units_unavailable()
@test _is_constraint_equal(observed_con, expected_con)
end
end
@testset "constraint_units_available_units_unavailable_default" begin
url_in = _test_constraint_unit_setup()
candidate_units = 3
number_of_units_when_candidates_units = 0
units_unavailable = 1
unit_availability_factor = 0.5
object_parameter_values = [
["unit", "unit_ab", "candidate_units", candidate_units],
["unit", "unit_ab", "units_unavailable", units_unavailable],
["unit", "unit_ab", "unit_availability_factor", unit_availability_factor],
]
relationships = [
["unit__investment_temporal_block", ["unit_ab", "hourly"]],
["unit__investment_stochastic_structure", ["unit_ab", "stochastic"]],
]
SpineInterface.import_data(url_in; relationships=relationships, object_parameter_values=object_parameter_values)
m = run_spineopt(url_in; log_level=0, optimize=false)
var_units_on = m.ext[:spineopt].variables[:units_on]
var_units_invested_available = m.ext[:spineopt].variables[:units_invested_available]
constraint = m.ext[:spineopt].constraints[:units_available]
@test length(constraint) == 2
scenarios = (stochastic_scenario(:parent), stochastic_scenario(:child))
time_slices = time_slice(m; temporal_block=temporal_block(:hourly))
@testset for (s, t) in zip(scenarios, time_slices)
key = (unit(:unit_ab), s, t)
var_u_on = var_units_on[key...]
var_u_inv_av = var_units_invested_available[key...]
expected_con = @build_constraint(var_u_on <= number_of_units_when_candidates_units + var_u_inv_av - units_unavailable)
con_key = (unit(:unit_ab), s, t)
con = constraint[con_key...]
observed_con = constraint_object(con)
@test _is_constraint_equal(observed_con, expected_con)
end
end
end

function test_constraint_unit_state_transition()
Expand Down
Loading