Skip to content

Commit c143931

Browse files
authored
Fix temporal resolution connection_ratio_out_in (#1147)
* Change t indice function * Fix t_high_resolution_path * Add missing paths from ng_out * Modify duration for the node in * Modify constraint and update test * Remove t_highest_resolution_path * change db to let the test run * add missing examples for integration tests * revert db change to test * Try another way * Specify indices for t, path * Add highest resolution and tests * Change test name * Add highest as default and keep the original * Roll back the json changes to solve conflicts * Roll back again * Add new parameter to the jsons * Retrieve a wrongly commited file
1 parent 62b1498 commit c143931

15 files changed

+224
-7
lines changed

examples/6_unit_system.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82616,6 +82616,13 @@
8261682616
"boolean_value_list",
8261782617
"Whether to use tight and compact constraint formulations."
8261882618
],
82619+
[
82620+
"model",
82621+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
82622+
true,
82623+
"boolean_value_list",
82624+
"Whether to use highest resolution for constraint ratio out in connection flow."
82625+
],
8261982626
[
8262082627
"model",
8262182628
"window_duration",

examples/capacity_planning.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2855,6 +2855,13 @@
28552855
"boolean_value_list",
28562856
"Whether to use tight and compact constraint formulations."
28572857
],
2858+
[
2859+
"model",
2860+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
2861+
true,
2862+
"boolean_value_list",
2863+
"Whether to use highest resolution for constraint ratio out in connection flow."
2864+
],
28582865
[
28592866
"model",
28602867
"window_duration",

examples/multi-year_investment_with_econ_params_with_milestones.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2844,6 +2844,13 @@
28442844
"boolean_value_list",
28452845
"Whether to use tight and compact constraint formulations."
28462846
],
2847+
[
2848+
"model",
2849+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
2850+
true,
2851+
"boolean_value_list",
2852+
"Whether to use highest resolution for constraint ratio out in connection flow."
2853+
],
28472854
[
28482855
"model",
28492856
"window_duration",

examples/multi-year_investment_with_econ_params_without_milestones.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,6 +2772,13 @@
27722772
"boolean_value_list",
27732773
"Whether to use tight and compact constraint formulations."
27742774
],
2775+
[
2776+
"model",
2777+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
2778+
true,
2779+
"boolean_value_list",
2780+
"Whether to use highest resolution for constraint ratio out in connection flow."
2781+
],
27752782
[
27762783
"model",
27772784
"window_duration",

examples/multi-year_investment_without_econ_params.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2935,6 +2935,13 @@
29352935
"boolean_value_list",
29362936
"Whether to use tight and compact constraint formulations."
29372937
],
2938+
[
2939+
"model",
2940+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
2941+
true,
2942+
"boolean_value_list",
2943+
"Whether to use highest resolution for constraint ratio out in connection flow."
2944+
],
29382945
[
29392946
"model",
29402947
"window_duration",

examples/reserves.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,13 @@
14791479
"boolean_value_list",
14801480
"Whether to use tight and compact constraint formulations."
14811481
],
1482+
[
1483+
"model",
1484+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
1485+
true,
1486+
"boolean_value_list",
1487+
"Whether to use highest resolution for constraint ratio out in connection flow."
1488+
],
14821489
[
14831490
"model",
14841491
"window_duration",

examples/rolling_horizon.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,13 @@
14791479
"boolean_value_list",
14801480
"Whether to use tight and compact constraint formulations."
14811481
],
1482+
[
1483+
"model",
1484+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
1485+
true,
1486+
"boolean_value_list",
1487+
"Whether to use highest resolution for constraint ratio out in connection flow."
1488+
],
14821489
[
14831490
"model",
14841491
"window_duration",

examples/simple_system.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,13 @@
14791479
"boolean_value_list",
14801480
"Whether to use tight and compact constraint formulations."
14811481
],
1482+
[
1483+
"model",
1484+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
1485+
true,
1486+
"boolean_value_list",
1487+
"Whether to use highest resolution for constraint ratio out in connection flow."
1488+
],
14821489
[
14831490
"model",
14841491
"window_duration",

examples/stochastic.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2765,6 +2765,13 @@
27652765
"boolean_value_list",
27662766
"Whether to use tight and compact constraint formulations."
27672767
],
2768+
[
2769+
"model",
2770+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
2771+
true,
2772+
"boolean_value_list",
2773+
"Whether to use highest resolution for constraint ratio out in connection flow."
2774+
],
27682775
[
27692776
"model",
27702777
"window_duration",

examples/unit_commitment.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,13 @@
14791479
"boolean_value_list",
14801480
"Whether to use tight and compact constraint formulations."
14811481
],
1482+
[
1483+
"model",
1484+
"use_highest_resolution_constraint_ratio_out_in_connection_flow",
1485+
true,
1486+
"boolean_value_list",
1487+
"Whether to use highest resolution for constraint ratio out in connection flow."
1488+
],
14821489
[
14831490
"model",
14841491
"window_duration",

src/constraints/constraint_ratio_out_in_connection_flow.jl

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,50 @@ exist for the other two cases.
4444
See also [fix\_ratio\_out\_in\_connection\_flow](@ref).
4545
"""
4646
function add_constraint_ratio_out_in_connection_flow!(m::Model, ratio_out_in, sense)
47-
_add_constraint!(
48-
m,
49-
ratio_out_in.name,
50-
m -> constraint_ratio_out_in_connection_flow_indices(m, ratio_out_in),
51-
(m, ind...) -> _build_constraint_ratio_out_in_connection_flow(m, ind..., ratio_out_in, sense),
47+
if use_highest_resolution_constraint_ratio_out_in_connection_flow(model=m.ext[:spineopt].instance)
48+
_add_constraint!(
49+
m,
50+
ratio_out_in.name,
51+
m -> constraint_ratio_out_in_connection_flow_indices_highest_resolution(m, ratio_out_in),
52+
(m, ind...) -> _build_constraint_ratio_out_in_connection_flow_highest_resolution(m, ind..., ratio_out_in, sense),
53+
)
54+
else
55+
_add_constraint!(
56+
m,
57+
ratio_out_in.name,
58+
m -> constraint_ratio_out_in_connection_flow_indices(m, ratio_out_in),
59+
(m, ind...) -> _build_constraint_ratio_out_in_connection_flow(m, ind..., ratio_out_in, sense),
60+
)
61+
end
62+
end
63+
64+
function _build_constraint_ratio_out_in_connection_flow_highest_resolution(m::Model, conn, ng_out, ng_in, s_path, t, ratio_out_in, sense)
65+
# NOTE: the `<sense>_ratio_<directions>_connection_flow` parameter uses the stochastic dimensions
66+
# of the second <direction>!
67+
@fetch connection_flow = m.ext[:spineopt].variables
68+
build_sense_constraint(
69+
+ sum(
70+
+ connection_flow[conn, n_out, d, s, t_long]
71+
for (conn, n_out, d, s, t_long) in connection_flow_indices(
72+
m;
73+
connection=conn,
74+
node=ng_out,
75+
direction=direction(:to_node),
76+
stochastic_scenario=s_path,
77+
t=t_in_t(m; t_short=t),
78+
);
79+
init=0,
80+
),
81+
sense,
82+
+ sum(
83+
+ connection_flow[conn, n_in, d, s_past, t_past]
84+
* ratio_out_in(m; connection=conn, node1=ng_out, node2=ng_in, stochastic_scenario=s_past, t=t_past)
85+
* weight
86+
for (conn, n_in, d, s_past, t_past, weight) in _past_connection_input_flow_indices(
87+
m, conn, ng_out, ng_in, s_path, t
88+
);
89+
init=0,
90+
),
5291
)
5392
end
5493

@@ -109,6 +148,44 @@ function add_constraint_min_ratio_out_in_connection_flow!(m::Model)
109148
add_constraint_ratio_out_in_connection_flow!(m, min_ratio_out_in_connection_flow, >=)
110149
end
111150

151+
function constraint_ratio_out_in_connection_flow_indices_highest_resolution(m::Model, ratio_out_in)
152+
(
153+
(connection=conn, node1=ng_out, node2=ng_in, stochastic_path=path, t=t)
154+
for (conn, ng_out, ng_in) in indices(ratio_out_in)
155+
if !_has_simple_fix_ratio_out_in_connection_flow(conn, ng_out, ng_in)
156+
for t in t_highest_resolution(
157+
m,
158+
Iterators.flatten(
159+
((t for (ng, t) in node_time_indices(m; node=ng_in)), (t for (ng, t) in node_time_indices(m; node=ng_out)))
160+
)
161+
)
162+
for path_out in active_stochastic_paths(
163+
m,
164+
connection_flow_indices(m; connection=conn, node=ng_out, direction=direction(:to_node), t=t_in_t(m; t_short=t))
165+
)
166+
for path in active_stochastic_paths(
167+
m,
168+
Iterators.flatten(
169+
(
170+
((stochastic_scenario=s,) for s in path_out),
171+
(
172+
ind
173+
for s in path_out
174+
for ind in connection_flow_indices(
175+
m;
176+
connection=conn,
177+
node=ng_in,
178+
direction=direction(:from_node),
179+
t=to_time_slice(m; t=_t_look_behind(conn, ng_out, ng_in, (s,), t)),
180+
temporal_block=anything,
181+
)
182+
),
183+
)
184+
)
185+
)
186+
)
187+
end
188+
112189
function constraint_ratio_out_in_connection_flow_indices(m::Model, ratio_out_in)
113190
(
114191
(connection=conn, node1=ng_out, node2=ng_in, stochastic_path=path, t=t)

templates/spineopt_template.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@
206206
["model", "shared_values", null, null, "A map from symbol to shared value."],
207207
["model", "use_connection_intact_flow", true, "boolean_value_list", "Whether to use `connection_intact_flow` variables, to capture the impact of connection investments on network characteristics via line outage distribution factors (LODF)."],
208208
["model", "use_tight_compact_formulations", false, "boolean_value_list", "Whether to use tight and compact constraint formulations."],
209+
["model", "use_highest_resolution_constraint_ratio_out_in_connection_flow", true, "boolean_value_list", "Whether to use highest resolution for constraint ratio out in connection flow."],
209210
["model", "window_duration", null, null, "The duration of the window in case it differs from roll_forward"],
210211
["model", "window_weight", 1, null, "The weight of the window in the rolling subproblem"],
211212
["model", "use_milestone_years", false, "boolean_value_list", "If set to true, the investment models uses milestone years. In other words, operational temporal blocks for one (milestone) year will be scaled up by the discounted duration to represent the entire investment period."],

test/constraints/constraint_connection.jl

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,12 +863,76 @@ function test_contraints_ptdf_lodf_duration()
863863
end
864864

865865
function test_constraint_ratio_out_in_connection_flow()
866+
@testset "constraint_ratio_out_in_connection_flow_highest_resolution" begin
867+
flow_ratio = 0.8
868+
model_end = Dict("type" => "date_time", "data" => "2000-01-01T04:00:00")
869+
class = "connection__node__node"
870+
relationship = ["connection_ab", "node_b", "node_a"]
871+
object_parameter_values = [
872+
["model", "instance", "model_end", model_end],
873+
["model", "instance", "use_highest_resolution_constraint_ratio_out_in_connection_flow", true] # this is the default value
874+
]
875+
relationships = [[class, relationship]]
876+
senses_by_prefix = Dict("min" => >=, "fix" => ==, "max" => <=)
877+
h_delay = 2
878+
connection_flow_delay = Dict("type" => "duration", "data" => string(h_delay, "h"))
879+
@testset for p in ("min", "fix", "max")
880+
url_in = _test_constraint_connection_setup()
881+
sense = senses_by_prefix[p]
882+
ratio = string(p, "_ratio_out_in_connection_flow")
883+
relationship_parameter_values = [
884+
[class, relationship, "connection_flow_delay", connection_flow_delay],
885+
[class, relationship, ratio, flow_ratio],
886+
]
887+
SpineInterface.import_data(
888+
url_in;
889+
relationships=relationships,
890+
object_parameter_values=object_parameter_values,
891+
relationship_parameter_values=relationship_parameter_values,
892+
)
893+
m = run_spineopt(url_in; log_level=0, optimize=false)
894+
var_connection_flow = m.ext[:spineopt].variables[:connection_flow]
895+
constraint = m.ext[:spineopt].constraints[Symbol(ratio)]
896+
@test length(constraint) == 4
897+
conn = connection(:connection_ab)
898+
n_from = node(:node_a)
899+
n_to = node(:node_b)
900+
d_from = direction(:from_node)
901+
d_to = direction(:to_node)
902+
scenarios_from = [repeat([stochastic_scenario(:child)], 3); repeat([stochastic_scenario(:parent)], 3)]
903+
time_slices_from = [
904+
reverse(time_slice(m; temporal_block=temporal_block(:hourly)))
905+
reverse(history_time_slice(m; temporal_block=temporal_block(:hourly)))
906+
]
907+
time_slices_to = reverse(time_slice(m; temporal_block=temporal_block(:two_hourly)))
908+
s_to = stochastic_scenario(:parent)
909+
@testset for (j, t_con) in enumerate(reverse(time_slice(m; temporal_block=temporal_block(:hourly))))
910+
s_from = scenarios_from[h_delay+j] # get the scenario before the delay
911+
t_from = time_slices_from[h_delay+j] # get the time slice before the delay
912+
var_conn_flow_from = var_connection_flow[conn, n_from, d_from, s_from, t_from]
913+
t_to = time_slices_to[(j+1)÷2]
914+
var_conn_flow_to = var_connection_flow[conn, n_to, d_to, s_to, t_to]
915+
expected_con = SpineOpt.build_sense_constraint(
916+
var_conn_flow_to,
917+
sense,
918+
flow_ratio * var_conn_flow_from,
919+
)
920+
path = unique([s_to; s_from])
921+
con_key = (conn, n_to, n_from, path, t_con)
922+
observed_con = constraint_object(constraint[con_key...])
923+
@test _is_constraint_equal(observed_con, expected_con)
924+
end
925+
end
926+
end
866927
@testset "constraint_ratio_out_in_connection_flow" begin
867928
flow_ratio = 0.8
868929
model_end = Dict("type" => "date_time", "data" => "2000-01-01T04:00:00")
869930
class = "connection__node__node"
870931
relationship = ["connection_ab", "node_b", "node_a"]
871-
object_parameter_values = [["model", "instance", "model_end", model_end]]
932+
object_parameter_values = [
933+
["model", "instance", "model_end", model_end],
934+
["model", "instance", "use_highest_resolution_constraint_ratio_out_in_connection_flow", false]
935+
]
872936
relationships = [[class, relationship]]
873937
senses_by_prefix = Dict("min" => >=, "fix" => ==, "max" => <=)
874938
@testset for conn_flow_minutes_delay in (150, 180, 225)

test/run_examples.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ objective_function_reference_values = Dict(
55
"simple_system.json" => 160714.28571428574,
66
"unit_commitment.json" => 98637.42857142858,
77
"rolling_horizon.json" => 65164.8571429,
8+
"multi-year_investment_with_econ_params_with_milestones" => 41025092.819187716,
9+
"multi-year_investment_with_econ_params_without_milestones" => 71720404.84378022,
10+
"multi-year_investment_without_econ_params" => 203360142.85714287,
11+
"capacity_planning" => 352127000,
12+
"stochastic" => 126964.2857142857,
813
)
914

1015
@testset for path in readdir(joinpath(dirname(@__DIR__), "examples"); join=true)

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ function _dismember_function(func)
153153
end
154154

155155
@testset begin
156-
include("data_structure/check_economic_structure.jl")
157156
include("data_structure/migration.jl")
158157
include("data_structure/check_data_structure.jl")
158+
include("data_structure/check_economic_structure.jl")
159159
include("data_structure/preprocess_data_structure.jl")
160160
include("data_structure/temporal_structure.jl")
161161
include("data_structure/stochastic_structure.jl")

0 commit comments

Comments
 (0)