Skip to content

Commit 54fc0d4

Browse files
authored
Bug fix related to investment data and TwoLevelTree (#93)
* Added Bool to remove unnecessary checks * Fixed the problems for the investment data
1 parent 19d149a commit 54fc0d4

5 files changed

Lines changed: 89 additions & 89 deletions

File tree

NEWS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Release notes
22

3+
## Version 0.10.3 (2026-06-10)
4+
5+
### Bug fixes
6+
7+
* Fixed addition bugs with `StrategicProfile` and `TwoLevelTree` in the checks for the investment data.
8+
39
## Version 0.10.2 (2026-06-09)
410

511
### Bug fixes

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "EnergyModelsBase"
22
uuid = "5d7e687e-f956-46f3-9045-6f5a5fd49f50"
33
authors = ["Lars Hellemo <Lars.Hellemo@sintef.no>, Julian Straus <Julian.Straus@sintef.no>"]
4-
version = "0.10.2"
4+
version = "0.10.3"
55

66
[deps]
77
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"

ext/EMIExt/checks.jl

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ Performs various checks on investment data introduced within EnergyModelsInvestm
8181
8282
## Checks
8383
- For each field with `TimeProfile`:
84-
- If the `TimeProfile` is a `StrategicProfile`, it will check that the profile is in
85-
accordance with the `TimeStructure`
84+
- If the `TimeProfile` is a `StrategicProfile` or `StrategicStochasticProfile`, it will
85+
check that the profile is in accordance with the `TimeStructure`
8686
- `TimeProfile`s in `InvestmentData` cannot include `OperationalProfile`,
8787
`RepresentativeProfile`, or `ScenarioProfile` as this is not allowed through indexing
8888
on the `TimeProfile`.
@@ -101,45 +101,39 @@ function check_inv_data(
101101
check_timeprofiles::Bool,
102102
)
103103
𝒯ᴵⁿᵛ = strategic_periods(𝒯)
104-
bool_sp = true
104+
bool = false # Boolean for subprofile checks
105+
bool_sp = true # Boolean
105106

106107
# Check on the individual time profiles
107108
for field_name fieldnames(typeof(inv_data))
108-
time_profile = getfield(inv_data, field_name)
109-
if isa(time_profile, Union{Investment,LifetimeMode})
110-
for sub_field_name fieldnames(typeof(time_profile))
111-
sub_time_profile = getfield(time_profile, sub_field_name)
109+
tp = getfield(inv_data, field_name)
110+
if isa(tp, Union{Investment,LifetimeMode})
111+
for sub_field_name fieldnames(typeof(tp))
112+
stp = getfield(tp, sub_field_name)
112113
submessage =
113114
"are not allowed for the field `" * String(sub_field_name) *
114115
"` of the mode `" * String(field_name) *
115116
"` in the investment data" * message * "."
116-
if isa(sub_time_profile, StrategicProfile) && check_timeprofiles
117-
@assert_or_log(
118-
length(sub_time_profile.vals) == length(𝒯ᴵⁿᵛ),
119-
"Field `" * string(sub_field_name) *
120-
"` does not match the strategic structure."
121-
)
117+
if (isa(stp, StrategicProfile) || isa(stp, StrategicStochasticProfile)) &&
118+
check_timeprofiles
119+
EMB.check_profile(string(sub_field_name), stp, 𝒯; bool)
122120
end
123-
EMB.check_strategic_profile(sub_time_profile, submessage)
121+
EMB.check_strategic_profile(stp, submessage)
124122
end
125123
end
126-
!isa(time_profile, TimeProfile) && continue
127-
isa(time_profile, FixedProfile) && continue
124+
(!isa(tp, TimeProfile) || isa(tp, FixedProfile)) && continue
128125
submessage =
129126
"are not allowed for the field `" * String(field_name) *
130127
"` in the investment data" * message * "."
131128

132-
if isa(time_profile, StrategicProfile) && check_timeprofiles
133-
@assert_or_log(
134-
length(time_profile.vals) == length(𝒯ᴵⁿᵛ),
135-
"Field `" * string(field_name) * "` does not match the strategic " *
136-
"structure in the investment data" * message * "."
137-
)
129+
if (isa(tp, StrategicProfile) || isa(tp, StrategicStochasticProfile)) &&
130+
check_timeprofiles
131+
EMB.check_profile(string(field_name), tp, 𝒯; bool)
138132
end
139-
if field_name == :initial
140-
bool_sp = EMB.check_strategic_profile(time_profile, submessage)
133+
if field_name == :initial || field_name == :max_inst
134+
bool_sp *= EMB.check_strategic_profile(tp, submessage)
141135
else
142-
EMB.check_strategic_profile(time_profile, submessage)
136+
EMB.check_strategic_profile(tp, submessage)
143137
end
144138
end
145139

@@ -156,7 +150,7 @@ function check_inv_data(
156150
submessage =
157151
"are not allowed for the capacity of the investment data " * message *
158152
", if investments are allowed and the chosen investment type is `NoStartInvData`."
159-
bool_sp = EMB.check_strategic_profile(capacity_profile, submessage)
153+
bool_sp *= EMB.check_strategic_profile(capacity_profile, submessage)
160154
if bool_sp
161155
@assert_or_log(
162156
all(capacity_profile[t_inv] EMI.max_installed(inv_data, t_inv) for t_inv 𝒯ᴵⁿᵛ),

src/checks.jl

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -347,25 +347,28 @@ function check_time_structure(x::AbstractElement, 𝒯)
347347
end
348348

349349
"""
350-
check_profile(fieldname, value::TimeProfile, 𝒯::TwoLevel)
351-
check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevel)
352-
check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLevel)
350+
check_profile(fieldname, value::TimeProfile, 𝒯::TwoLevel; bool::Bool=true)
351+
check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevel; bool::Bool=true)
352+
check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLevel; bool::Bool=true)
353353
354-
check_profile(fieldname, value::TimeProfile, 𝒯::TwoLevelTree)
355-
check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevelTree)
356-
check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLevelTree)
354+
check_profile(fieldname, value::TimeProfile, 𝒯::TwoLevelTree; bool::Bool=true)
355+
check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevelTree; bool::Bool=true)
356+
check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLevelTree; bool::Bool=true)
357357
358358
Check that an individual `TimeProfile` corresponds to the time structure `𝒯`. The individual
359359
checks are depending on the profile type and the time structure.
360+
361+
The key word argument `bool` is used to identify whether subprofiles should be checked
362+
(`true` as default) or not (`false`).
360363
"""
361-
function check_profile(fieldname, value::TimeProfile, 𝒯::TwoLevel)
364+
function check_profile(fieldname, value::TimeProfile, 𝒯::TwoLevel; bool::Bool=true)
362365
𝒯ᴵⁿᵛ = strategic_periods(𝒯)
363-
for t_inv 𝒯ᴵⁿᵛ
366+
bool && for t_inv 𝒯ᴵⁿᵛ
364367
p_msg = "strategic period $(t_inv.sp)"
365368
check_profile(fieldname, value, t_inv.operational, p_msg)
366369
end
367370
end
368-
function check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevel)
371+
function check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevel; bool::Bool=true)
369372
𝒯ᴵⁿᵛ = strategic_periods(𝒯)
370373

371374
len_vals = length(value.vals)
@@ -380,7 +383,7 @@ function check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevel)
380383
@assert_or_log(
381384
len_vals == len_ts, "The `TimeProfile` of field `" * string(fieldname) * message
382385
)
383-
for t_inv 𝒯ᴵⁿᵛ
386+
bool && for t_inv 𝒯ᴵⁿᵛ
384387
p_msg = "strategic period $(t_inv.sp)"
385388
check_profile(
386389
fieldname,
@@ -390,7 +393,7 @@ function check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevel)
390393
)
391394
end
392395
end
393-
function check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLevel)
396+
function check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLevel; bool::Bool=true)
394397
@warn(
395398
"Using `StrategicStochasticProfile` with `TwoLevel` is dangerous, " *
396399
"as it may lead to unexpected behaviour. " *
@@ -401,14 +404,14 @@ function check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLe
401404
prof = StrategicProfile([op_prof[1] for op_prof value.vals])
402405
check_profile(fieldname, prof, 𝒯)
403406
end
404-
function check_profile(fieldname, value::TimeProfile, 𝒯::TwoLevelTree)
407+
function check_profile(fieldname, value::TimeProfile, 𝒯::TwoLevelTree; bool::Bool=true)
405408
𝒯ᴵⁿᵛ = strategic_periods(𝒯)
406-
for t_inv 𝒯ᴵⁿᵛ
409+
bool && for t_inv 𝒯ᴵⁿᵛ
407410
p_msg = "branch $(t_inv.branch) in strategic period $(t_inv.sp)"
408411
check_profile(fieldname, value, t_inv.operational, p_msg)
409412
end
410413
end
411-
function check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevelTree)
414+
function check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevelTree; bool::Bool=true)
412415
𝒯ˢˢᶜ = strategic_scenarios(𝒯)
413416
t_inv_vec = []
414417

@@ -426,7 +429,7 @@ function check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevelTree)
426429
@assert_or_log(
427430
len_vals == len_ts, "The `TimeProfile` of field `" * string(fieldname) * message,
428431
)
429-
for t_inv 𝒯ᴵⁿᵛ
432+
bool && for t_inv 𝒯ᴵⁿᵛ
430433
t_inv t_inv_vec && continue
431434
push!(t_inv_vec, t_inv)
432435

@@ -440,7 +443,7 @@ function check_profile(fieldname, value::StrategicProfile, 𝒯::TwoLevelTree)
440443
end
441444
end
442445
end
443-
function check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLevelTree)
446+
function check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLevelTree; bool::Bool=true)
444447
# Check for the number of strategic periods
445448
len_vals = length(value.vals)
446449
len_ts = n_strat_per(𝒯)
@@ -475,7 +478,7 @@ function check_profile(fieldname, value::StrategicStochasticProfile, 𝒯::TwoLe
475478
end
476479

477480
# Check the sub profiles
478-
for t_inv strategic_periods(𝒯)
481+
bool && for t_inv strategic_periods(𝒯)
479482
p_msg = "branch $(t_inv.branch) in strategic period $(t_inv.sp)"
480483
sp_prof = value.vals[minimum([t_inv.sp, length(value.vals)])]
481484
check_profile(

0 commit comments

Comments
 (0)