Skip to content

Identification of sub time structures #78

Description

@JulStraus

Problem statement

In the current stage, we do not know what time structures are within the top time structure, even when considering the parametric input.

Consider the following example:

using TimeStruct
# Creation of the time structure
day = SimpleTimes(24, 1);
opscen_summer = OperationalScenarios(2, [day, day], [0.5, 0.5]);
opscen_winter = OperationalScenarios(2, [day, day], [0.5, 0.5])
rep = RepresentativePeriods(2, 8760.0, [25, 25]/50, [opscen_summer, opscen_winter]);
ts = TwoLevel(n_sp, dur_sp, rep, op_per_strat=8760.0);

The time structure is in this case of type TwoLevel{Int64, Int64, RepresentativePeriods{Float64, Int64, OperationalScenarios{Int64, SimpleTimes{Int64}}}}. If we change it a bit to

rep = RepresentativePeriods(2, 8760.0, [25, 25]/50, [opscen_summer, day]);
ts = TwoLevel(n_sp, dur_sp, rep, op_per_strat=8760.0);

we lost the knowledge as it is not of type TwoLevel{Int64, Int64, RepresentativePeriods{Float64, Int64, TimeStructure{Int64}}}. It can however be beneficial to have an understanding of whether a time structure has representative periods and operational scenarios for only declaring variables when these are required. A current (crude) implementation in EnergyModelsBase is rather limited and does not allow for a TwoLevelTree.

Potential solutions

We can create an iterative procedure which identifies whether operational scenarios are required:

function has_opscenarios(ts::TwoLevelTree, tmp::Bool = false)
    for strat_node ∈ ts.nodes
        tmp = has_opscenarios(strat_node.operational, tmp)
        tmp && break
    end
    return tmp
end
function has_opscenarios(ts::TwoLevel, tmp::Bool = false)
    for sub_ts ∈ ts.operational
        tmp = has_opscenarios(sub_ts, tmp)
        tmp && break
    end
    return tmp
end
function has_opscenarios(ts::RepresentativePeriods, tmp::Bool = false)
    for sub_ts ∈ ts.rep_periods
        tmp = has_opscenarios(sub_ts, tmp)
        tmp && break
    end
    return tmp
end
has_opscenarios(ts::OperationalScenarios, tmp::Bool = false) = true
has_opscenarios(ts::SimpleTimes, tmp::Bool = false) = false
has_opscenarios(ts::CalendarTimes, tmp::Bool = false) = false

A similar procedure could also be declared for RepresentativePeriods. There may still be potential problems in a model if a mixed time structure is created and these implications are not considered, but I think that it would be a good support for external users when creating models.

Note

I would hope that we get this through before 1.0. It should however be included at latest 1.0

Activity

  1. added this to the v1.0 milestone on Oct 21, 2025
  2. self-assigned this
    on Oct 21, 2025
  3. JulStraus commented on Oct 13, 2026

    @JulStraus
    CollaboratorAuthor

    Given that it is about 1 year old, are there any thoughts regarding the implementation? @trulsf or @hellemo? I do not see any harm in adding it.

  4. trulsf commented on Oct 16, 2026

    @trulsf
    Member

    I also see no harm in adding it.

    I would prefer to leave out the tmp in the signature and do e.g.

    has_opscenarios(ts::TwoLevel) = any(has_opscenarios, ts.operational)
    

    and similarly for other functions. Should the functionality also be provided for periods? E.g. has_opscenarios(sp::StrategicPeriod).

  5. JulStraus commented on Oct 16, 2026

    @JulStraus
    CollaboratorAuthor

    I also see no harm in adding it.
    I would prefer to leave out the tmp in the signature and do e.g.

    has_opscenarios(ts::TwoLevel) = any(has_opscenarios, ts.operational)
    

    Seems reasonable to me to leave out temp. The reason why I proposed the for loop was to explicitly break once it was detected. I realized now that any is doing the same.

    and similarly for other functions. Should the functionality also be provided for periods? E.g. has_opscenarios(sp::StrategicPeriod).

    I would guess so? Then again, for me, the key factor is that I only want to declare variables over operational scenarios or representative periods when these are present. This is not necessarily equally important for, e.g., a StrategicPeriod.

    I will implement a version of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions