Methods - Internal

Index

Extension functions

EnergyModelsRecedingHorizon.update_init_data!Function
update_init_data!(m, ri::AbstractReset, x::AbstractElement, idp::InitDataPath, opers_implᵣₕ)

Updates the values of AbstractElement x for the AbstractReset ri with the value specified by the key of the idp.

source
EMRH.update_init_data!(m, ri::AbstractReset, l::Transmission, idp::TransInitDataPath, opers_implᵣₕ)

Updates the initial values of Transmission corridor l for the AbstractReset ri with the value specified by the key of the TransInitDataPath idp.

The mode for the variable is identified through the field idx of TransInitDataPath.

source

Utility functions

EnergyModelsRecedingHorizon.update_results!Function
update_results!(results, m, 𝒰, opers, 𝒽)

Updates results given the optimization results m for the times opers, performed in horizon 𝒽. The results are indexed by the elements in the provided case (here accessed using the UpdateCase 𝒰).

source
EnergyModelsRecedingHorizon.save_resultsFunction
save_results(model::Model; directory=joinpath(pwd(),"csv_files"))
save_results(results::Dict{Symbol, AbstractDataFrame}; directory=joinpath(pwd(),"csv_files"))

Saves the model results of all variables as CSV files. The model results are saved in the specified directory. If no directory is specified, it will create, if necessary, a new directory "csv_files" in the current working directory and save the files in said directory.

source
EnergyModelsRecedingHorizon.get_resultsFunction
get_results(m::JuMP.Model)

Function returning the values of the optimized model m. Prints a warning message for currently unsupported types without extracting their value.

source
EnergyModelsRecedingHorizon.get_results_dfFunction
get_results_df(m::JuMP.Model)

Function returning the values of the optimized model m as a DataFrame. Prints a warning message for currently unsupported types without extracting their value.

source

Miscellaneous functions

EnergyModelsRecedingHorizon._create_lens_dictFunction
_create_lens_dict(𝒳::Vector{<:AbstractElement}
_create_lens_dict(x::Union{AbstractElement, RecHorEnergyModel})

Returns a dictionary with the field id as keys and lenses pointing to fields that are updated in the individual type instances as values. The individual field ids are created through calling the function _find_update_paths, and the lenses are created with _create_lens_for_field.

Lenses are created for

  1. all OperationalProfiles,
  2. other AbstractElement, and
  3. InitData.

Example

using EnergyModelsBase
using EnergyModelsRecedingHorizon
using TimeStruct
const EMRH = EnergyModelsRecedingHorizon

# Generate objects
cap_prof = OperationalProfile([20, 300])
em_prof = OperationalProfile([1, 2])
price_prof = OperationalProfile([40, 60])

power = ResourceCarrier("power", 0.0)
co2 = ResourceEmit("co2", 1.0)

source1 = RefSource(
    "source1",
    cap_prof,
    FixedProfile(100),
    FixedProfile(0),
    Dict(power => 1),
    [EmissionsProcess(Dict(co2 => em_prof))]
)
source2 = RefSource(
    "source2",
    FixedProfile(100),
    price_prof,
    FixedProfile(0),
    Dict(power => 1),
)

# Create a dictionary containing lenses to the OperationalProfile
d_all = EMRH._create_lens_dict([source1, source2])
# Returns Dict{RefSource, Dict{Vector{Any}}} with 2 entries:
 n_source1 => Dict{Vector{Any}, Any}([:data, "[1]", :emissions, co2, OperPath()]=>_.data[1].emissions[co2], [:cap, OperPath()]=>_.cap)
 n_source2 => Dict{Vector{Any}, PropertyLens{:opex_var}}([:opex_var, OperPath()]=>_.opex_var)

d_s1 = EMRH._create_lens_dict(source1)
# Returns Dict{Vector{Any}, Any} with 2 entries:
 [:data, "[1]", :emissions, co2, OperPath()] => _.data[1].emissions[co2]
 [:cap, OperPath()]                          => _.cap
source

Identification functions

EnergyModelsRecedingHorizon._find_update_pathsMethod
_find_update_paths(x::Union{AbstractElement, Resource, RecHorEnergyModel})
_find_update_paths(x::StorageValueCuts)

Returns all paths within an AbstractElement, a Resource, a RecHorEnergyModel, or a StorageValueCuts that must be updated in the receding horizon framework as Vector{Vector}.

The individual subfunctions are given as:

_find_update_paths(field::AbstractElement, current_path::Vector{Any}, all_paths::Vector{Any})
_find_update_paths(field::StorageValueCut, current_path::Vector{Any}, all_paths::Vector{Any})
_find_update_paths(field::Vector{<:Data}, current_path::Vector{Any}, all_paths::Vector{Any})
_find_update_paths(field::T, current_path::Vector{Any}, all_paths::Vector{Any}) where {T<:Union{Data, EMB.AbstractStorageParameters, ElementValue}}
_find_update_paths(field::AbstractDict, current_path::Vector{Any}, all_paths::Vector{Any})
_find_update_paths(field::OperationalProfile, current_path::Vector{Any}, all_paths::Vector{Any})
_find_update_paths(field::StrategicProfile, current_path::Vector{Any}, all_paths::Vector{Any})
_find_update_paths(field::Any, current_path::Vector{Any}, all_paths::Vector{Any})
_find_update_paths(field::AbstractInitData, current_path::Vector{Any}, all_paths::Vector{Any})
_find_update_paths(field::InitData, current_path::Vector{Any}, all_paths::Vector{Any})
Introducing new `AbstractInitData`

When introducing a new subtype to AbstractInitData, you must also create a new method for this function as it is not possible to cover all potential cases in which the new data is designed.

Example

power = ResourceCarrier("power", 0.0)
co2 = ResourceEmit("co2", 1.0)
sink = RefSink(
    "a_sink",                                               # Field `:id`
    FixedProfile(1e5),                                      # Field `:cap`
    Dict(:surplus => OperationalProfile(zeros(10)),
         :deficit => OperationalProfile(10*ones(10))),      # Field `:penalty`
    Dict(power => 1),                                       # Field `:input`
    [EmissionsProcess(Dict(co2 => OperationalProfile(rand(10))))] # Field `:data`
)

EMRH._find_update_paths(sink)
# returns a 3-element Vector{Any}:
 Any[:penalty, "[:deficit]", EnergyModelsRecedingHorizon.OperPath()]
 Any[:penalty, "[:surplus]", EnergyModelsRecedingHorizon.OperPath()]
 Any[:data, "[1]", :emissions, co2, EnergyModelsRecedingHorizon.OperPath()]

# The function can also be used for checking other `types`:
all_paths = []
current_path = Any[:a_path]
a_dict = Dict(:a => Dict(:b1 => Dict(:c => OperationalProfile([1])),
    :b2 => OperationalProfile([1]), :b3 => [1]))

EMRH._find_update_paths(a_dict, current_path, all_paths)
# all_paths is now a 2-element Vector{Any}:
 Any[:a_path, "[:a]", "[:b2]", EnergyModelsRecedingHorizon.OperPath()]
 Any[:a_path, "[:a]", "[:b1]", "[:c]", EnergyModelsRecedingHorizon.OperPath()]
source
EnergyModelsRecedingHorizon._dict_keyFunction
_dict_key(key::Symbol)
_dict_key(key::String)
_dict_key(key::Resource)

Function for translating a dictionary key type to an input which can be parsed into a lens.

source
EnergyModelsRecedingHorizon._create_lens_for_fieldFunction
_create_lens_for_field(field_id::Vector{<:Any})

Returns a lens, which can be used to inspect or reset variables. The lens is based on the field_id obtained through the function _find_update_paths.

Example:

using Accessors: @reset
using EnergyModelsBase
using EnergyModelsRecedingHorizon
using TimeStruct
const EMRH = EnergyModelsRecedingHorizon

cap_prof = OperationalProfile([20, 300])
em_prof = OperationalProfile([1,2])
power = ResourceCarrier("power", 0.0)
co2 = ResourceEmit("co2", 1.0)

source = RefSource(
    "power_source",                         # Node id or name
    cap_prof,                               # Capacity
    FixedProfile(100),                      # Variable OPEX
    FixedProfile(0),                        # Fixed OPEX
    Dict(power => 1),                       # Output from the node
    [EmissionsProcess(Dict(co2 => em_prof))] # Line above: CO2 process emissions
)

paths_oper_source = EMRH._find_update_paths(source)
@assert all(paths_oper_source .== Any[
    [:cap, EMRH.OperPath()], [:data, "[1]", :emissions, co2, EMRH.OperPath()]
])
lens_source_cap = EMRH._create_lens_for_field(paths_oper_source[1])
lens_source_data = EMRH._create_lens_for_field(paths_oper_source[2])

# Check that the values returned through the lenses are based on the actual values
@assert all(cap_prof == lens_source_cap(source))
@assert all(em_prof == lens_source_data(source))

# Lenses can also be used for resetting values using @reset
cap_prof_new = OperationalProfile([90,100])
@reset lens_source_cap(source) = cap_prof_new
@assert all(cap_prof_new == lens_source_cap(source))
source
EnergyModelsRecedingHorizon._path_typeFunction
_path_type(val::Symbol)
_path_type(val::String)
_path_type(val::Resource)
_path_type(val::AbstractPath)

Translate the individual value to the required format for creating the lense string.

In the case of a resource, it creates a global variable calles res which can be evaluated in the parse.

source

Functions for resetting values

EnergyModelsRecedingHorizon._add_elements!Function
_add_elements!(𝒰::UpdateCase, 𝒫::Vector{T}) where {T<:Resource}
_add_elements!(𝒰::UpdateCase, 𝒳::Vector{T}) where {T<:AbstractElement}

Add the vector of Resources or AbstractElement substitution types to the UpdateCase 𝒰 for a given Vector{<:Resource} or Vector{<:AbstractElement}.

source
EnergyModelsRecedingHorizon._update_future_value!Function
_update_future_value!(𝒮ᵛ::Vector{FutureValueSub{T}}, time_elapsed::Real) where {T<:StorageValueCuts}
_update_future_value!(𝒮ᵛ::Vector{FutureValueSub{T}}, time_elapsed::Real) where {T<:TypeFutureValue}

Update the value of TimeWeightReset based on the time time_elapsed at the end of the TimeStructure.

If a cut is given at the end time of an operational period, the weight is 1 for the given cut and 0 for other. When the optimization end time is between cuts, the weights scales the weight of the nearest cuts such that they are weighted linearly.

source
EnergyModelsRecedingHorizon._update_update_case!Function
_update_update_case!(𝒰, opers, 𝒯ᵣₕ)

Update the UpdateCase 𝒰 with the new values in the optimization problem given by the time structure 𝒯ᵣₕ.

In addition, the UpdateCase 𝒰 is updated with the new mapping between the operational periods of the optimization (through 𝒯ᵣₕ) and the original (through opers) problem.

source
EnergyModelsRecedingHorizon._reset_fieldMethod
_reset_field(x_rh, res_type::ElementReset, 𝒰::UpdateCase, opers::Vector{<:TS.TimePeriod})
_reset_field(x_rh, res_type::Union{InitReset, TimeWeightReset}, 𝒰::UpdateCase, opers::Vector{<:TS.TimePeriod})
_reset_field(x_rh, res_type::OperReset, 𝒰::UpdateCase, opers::Vector{<:TS.TimePeriod})

Resets the field expressed through res_type of element x_rh with the new value. The type of the new value is depending on the specified res_type:

  1. res_type::ElementReset uses 𝒰 for identifying the new element,
  2. res_type::Union{InitReset, TimeWeightReset} uses the value in res_type directly,
  3. res_type::OperReset creates a new operational profile based on the original operational profile in res_type and the set of operational periods opers.
source

The following function is introduced for parametric types in which the type is not deducible from the input and for types with inner constructors:

ConstructionBase.constructorofFunction
Accessors.ConstructionBase.constructorof(obj::Type{<:Storage})

Allows using @reset for an obj <: Storage, which is declared as parametric type without the possibility to deduce the possibility to deduce the type parameter from the provided input.

Note

Dispatch on this function for functions using inner constructors, in order for @reset to work.

source

Future value functions

EnergyModelsRecedingHorizon.get_future_value_expressionFunction
get_future_value_expression(m, 𝒱::Vector{StorageValueCuts}, 𝒯ᴵⁿᵛ::TS.AbstractStratPers, modeltype::EnergyModel)
get_future_value_expression(m, 𝒱::Vector{TypeFutureValue}, 𝒯ᴵⁿᵛ::TS.AbstractStratPers, modeltype::EnergyModel)

Returns the cost expression for the individual future values.

In the case of StorageValueCuts, the expression equals the weighted sum of the future_value of all active cuts. Inactive cuts are weighted with 0 but still included to keep the number of variables unchanged.

In the case of TypeFutureValue, the expression equals the sum of all values.

source
EnergyModelsRecedingHorizon.create_future_value_coupleFunction
create_future_value_couple(m, v::StorageValueCuts, 𝒯, modeltype::EnergyModel)
create_future_value_couple(m, v::StorageValueCuts, 𝒩::Vector{<:EMB.Node}, 𝒯, modeltype::EnergyModel)
create_future_value_couple(m, v::TypeFutureValue, 𝒯, modeltype::EnergyModel)
create_future_value_couple(m, v::TypeFutureValue, 𝒩::Vector{<:EMB.Node}, 𝒯, modeltype::EnergyModel)

Adds the constraints for the individual future values without the interaction with any other AbstractElement.

In the case of StorageValueCuts:

  • If 𝒩 is not added, that is in the instance for the single couplings, the function adds the cut constraints for all cuts.
  • If 𝒩 is added, that is in the instance for FutureValue-Node couplings, the function returns nothing.

In the case of TypeFutureValue:

  • If 𝒩 is not added, that is in the instance for the single couplings, the function returns nothing.
  • If 𝒩 is added, that is in the instance for FutureValue-Node couplings, the function calculates the future value for the given type.
source

The following functions for accessing fields of the types are introduced:

EnergyModelsRecedingHorizon.coefficientsFunction
coefficients(svc::StorageValueCut)

Returns the cut coefficients associated with the level of the given Storage nodes.

source
coefficients(v::TypeFutureValue)

Returns the the cofficients dictionary of of the future value v.

source