Internal functions
Index
EnergyModelsBase.check_case_data
EnergyModelsBase.check_data
EnergyModelsBase.check_fixed_opex
EnergyModelsBase.check_model
EnergyModelsBase.check_node
EnergyModelsBase.check_node_data
EnergyModelsBase.check_profile
EnergyModelsBase.check_representative_profile
EnergyModelsBase.check_scenario_profile
EnergyModelsBase.check_strategic_profile
EnergyModelsBase.check_time_structure
EnergyModelsBase.collect_types
EnergyModelsBase.compile_logs
EnergyModelsBase.constraints_emissions
EnergyModelsBase.constraints_level_bounds
EnergyModelsBase.constraints_level_iterate
EnergyModelsBase.constraints_level_rp
EnergyModelsBase.constraints_level_scp
EnergyModelsBase.constraints_links
EnergyModelsBase.constraints_node
EnergyModelsBase.create_link
EnergyModelsBase.has_charge_OPEX_fixed
EnergyModelsBase.has_charge_OPEX_var
EnergyModelsBase.has_charge_cap
EnergyModelsBase.has_discharge_OPEX_fixed
EnergyModelsBase.has_discharge_OPEX_var
EnergyModelsBase.has_discharge_cap
EnergyModelsBase.has_level_OPEX_fixed
EnergyModelsBase.has_level_OPEX_var
EnergyModelsBase.is_network_node
EnergyModelsBase.is_resource_emit
EnergyModelsBase.is_sink
EnergyModelsBase.is_source
EnergyModelsBase.is_storage
EnergyModelsBase.link_res
EnergyModelsBase.link_sub
EnergyModelsBase.nodes_not_av
EnergyModelsBase.nodes_not_sub
EnergyModelsBase.nodes_sub
EnergyModelsBase.objective
EnergyModelsBase.res_em
EnergyModelsBase.res_not
EnergyModelsBase.res_sub
EnergyModelsBase.sort_types
EnergyModelsBase.variables_capacity
EnergyModelsBase.variables_capex
EnergyModelsBase.variables_emission
EnergyModelsBase.variables_flow
EnergyModelsBase.variables_nodes
EnergyModelsBase.variables_opex
Extension functions
EnergyModelsBase.create_link
— Functioncreate_link(m, 𝒯, 𝒫, l, formulation::Formulation)
Set the constraints for a simple Link
(input = output). Can serve as fallback option for all unspecified subtypes of Link
.
EnergyModelsBase.objective
— Methodobjective(m, 𝒩, 𝒯, 𝒫, modeltype::EnergyModel)
Create the objective for the optimization problem for a given modeltype.
The default option includes to the objective function:
- the variable and fixed operating expenses for the individual nodes and
- the cost for the emissions.
The values are not discounted.
This function serve as fallback option if no other method is specified for a specific modeltype
.
Constraint functions
EnergyModelsBase.constraints_emissions
— Functionconstraints_emissions(m, 𝒩, 𝒯, 𝒫, modeltype::EnergyModel)
Create constraints for the emissions accounting for both operational and strategic periods.
EnergyModelsBase.constraints_links
— Functionconstraints_links(m, 𝒩, 𝒯, 𝒫, ℒ, modeltype::EnergyModel)
Call the function create_link
for link formulation
EnergyModelsBase.constraints_node
— Functionconstraints_node(m, 𝒩, 𝒯, 𝒫, ℒ, modeltype::EnergyModel)
Create link constraints for each n ∈ 𝒩
depending on its type and calling the function create_node(m, n, 𝒯, 𝒫)
for the individual node constraints.
Create constraints for fixed OPEX.
EnergyModelsBase.constraints_level_iterate
— Functionconstraints_level_iterate(
m,
n::Storage,
prev_pers::PreviousPeriods,
cyclic_pers::CyclicPeriods,
per,
ts::RepresentativePeriods,
modeltype::EnergyModel,
)
Iterate through the individual time structures of a Storage
node. This iteration function should in general allow for all necessary functionality for incorporating modifications.
In the case of RepresentativePeriods
, this is achieved through calling the function constraints_level_rp
to introduce, e.g., cyclic constraints as it is in the default case.
constraints_level_iterate(
m,
n::Storage,
prev_pers::PreviousPeriods,
per,
ts::OperationalScenarios,
modeltype::EnergyModel,
)
In the case of OperationalScenarios
, this is achieved through calling the function constraints_level_scp
. In the default case, no constraints are added.
constraints_level_iterate(
m,
n::Storage,
prev_pers::PreviousPeriods,
per,
ts::SimpleTimes,
modeltype::EnergyModel,
)
In the case of SimpleTimes
, the iterator function is at its lowest level. In this situation,the previous level is calculated using the function previous_level
and used for the storage balance. The the approach for calculating the previous_level
is depending on the types in the parameteric type PreviousPeriods
.
In addition, additional bounds can be included on the initial level within an operational period.
EnergyModelsBase.constraints_level_rp
— Functionconstraints_level_rp(m, n::Storage, per, modeltype::EnergyModel)
Provides additional contraints for representative periods.
The default approach is to set the total change in all representative periods within a strategic period to 0. This implies that the Storage
node cannot accumulate energy between individual strategic periods.
constraints_level_rp(m, n::Storage{<:Accumulating}, per, modeltype::EnergyModel)
When a Storage{<:Accumulating}
is used, the cyclic constraint for restricting the level change within a strategic period to 0 (through setting the sum of :stor_level_Δ_rp
within a strategic period to 0) is not implemented as accumulation within a strategic period is desirable.
This implies that Accumulating
behaviours require the developer to introduce the function previous_level
in the case of prev_pers = PreviousPeriods{<:NothingPeriod, Nothing, Nothing}
.
constraints_level_rp(m, n::Storage{CyclicRepresentative}, per, modeltype::EnergyModel)
When a Storage{CyclicRepresentative}
is used, the change in the representative period is constrained to 0.
EnergyModelsBase.constraints_level_scp
— Functionconstraints_level_scp(m, n::Storage, per, modeltype::EnergyModel)
Provides additional constraints for scenario periods.
The default approach is to not provide any constraints.
constraints_level_scp(m, n::Storage{CyclicRepresentative}, per, modeltype::EnergyModel)
When a Storage{CyclicRepresentative} is used, the final level in an operational scenario is constrained to be the same in all operational scenarios.
EnergyModelsBase.constraints_level_bounds
— Functionconstraints_level_bounds(
m,
n::Storage,
t::TS.TimePeriod,
prev_pers::TS.TimePeriod,
modeltype::EnergyModel,
)
Provides bounds on the initial storage level in an operational period to account for the level being modelled at the end of the operational periods.
The default approach is to not provide bounds.
constraints_level_bounds(
m,
n::Storage,
t::TS.TimePeriod,
cyclic_pers::CyclicPeriods{<:TS.AbstractRepresentativePeriod},
modeltype::EnergyModel,
)
When representative periods are used and the previous operational period is nothing
, then bounds are incorporated to avoid that the initial level storage level is violating the maximum and minimum level.
Variable creation functions
EnergyModelsBase.variables_capacity
— Functionvariables_capacity(m, 𝒩, 𝒯, modeltype::EnergyModel)
Declaration of different capacity variables for nodes 𝒩ⁿᵒᵗ
that are neither Storage
nor Availability
nodes. These variables are:
:cap_use
- use of a technology node in each operational period and:cap_inst
- installed capacity in each operational period in terms of either:flow_in
or:flow_out
(depending on noden ∈ 𝒩
)
Declaration of different storage variables for Storage
nodes 𝒩ˢᵗᵒʳ
. These variables are:
:stor_level
- storage level at the end of each operational period.:stor_level_Δ_op
- storage level change in each operational period.:stor_level_Δ_rp
- storage level change in each representative period. These variables are only created if the time structure includes representative periods.:stor_level_Δ_op
- storage level change in each strategic period. These variables are optional and created throughSparseVariables
.:stor_level_inst
- installed capacity for storage in each operational period, constrained in the operational case to the provided capacity in the storage parameters used in the field:level
.:stor_charge_use
- storage charging use in each operational period.:stor_charge_inst
- installed charging capacity, e.g., power, in each operational period, constrained in the operational case to the provided capacity in the storage parameters used in the field:charge
. This variable is only defined if theStorage
node has a fieldcharge.
:stor_discharge_use
- storage discharging use in each operational period.:stor_discharge_inst
- installed discharging capacity, e.g., power, in each operational period, constrained in the operational case to the provided capacity in the storage parameters used in the field:discharge
. This variable is only defined if theStorage
node has a fielddischarge.
EnergyModelsBase.variables_capex
— Methodvariables_capex(m, 𝒩, 𝒯, 𝒫, modeltype::EnergyModel)
Declaration of the CAPEX variables of the model for each investment period 𝒯ᴵⁿᵛ ∈ 𝒯
. Empty for operational models but required for multiple dispatch in investment model.
EnergyModelsBase.variables_emission
— Functionvariables_emission(m, 𝒩, 𝒯, 𝒫, modeltype::EnergyModel)
Declaration of emission variables per technology node with emissions n ∈ 𝒩ᵉᵐ
and emission resource 𝒫ᵉᵐ ∈ 𝒫
.
The emission variables are differentiated in:
:emissions_node
- emissions of a node in an operational period,:emissions_total
- total emissions in an operational period, and:emissions_strategic
- total strategic emissions, constrained to an upper limit based on the fieldemission_limit
of theEnergyModel
.
EnergyModelsBase.variables_flow
— Functionvariables_flow(m, 𝒩, 𝒯, 𝒫, ℒ, modeltype::EnergyModel)
Declaration of the individual input (:flow_in
) and output (:flow_out
) flowrates for each technological node n ∈ 𝒩
and link l ∈ ℒ
(:link_in
and :link_out
).
EnergyModelsBase.variables_opex
— Functionvariables_opex(m, 𝒩, 𝒯, 𝒫, modeltype::EnergyModel)
Declaration of the OPEX variables (:opex_var
and :opex_fixed
) of the model for each period 𝒯ᴵⁿᵛ ∈ 𝒯
. Variable OPEX can be non negative to account for revenue streams.
EnergyModelsBase.variables_nodes
— Functionvariables_nodes(m, 𝒩, 𝒯, modeltype::EnergyModel)
Loop through all node types and create variables specific to each type. This is done by calling the method variables_node
on all nodes of each type.
The node type representing the widest cathegory will be called first. That is, variables_node
will be called on a Node
before it is called on NetworkNode
-nodes.
Check functions
EnergyModelsBase.check_data
— Functioncheck_data(case, modeltype::EnergyModel, check_timeprofiles::Bool)
Check if the case data is consistent. Use the @assert_or_log
macro when testing. Currently only checking node data.
EnergyModelsBase.check_case_data
— Functioncheck_case_data(case)
Checks the case
dictionary is in the correct format.
Checks
- The dictionary requires the keys
:T
,:nodes
,:links
, and:products
. - The individual keys are of the correct type, that is
:T::TimeStructure
,:nodes::Vector{<:Node}
,:links::Vector{<:Link}
, and:products::Vector{<:Resource}
.
EnergyModelsBase.check_model
— Functioncheck_model(case, modeltype::EnergyModel, check_timeprofiles::Bool)
Checks the modeltype
.
Checks
- All
ResourceEmit
s require a corresponding value in the fieldemission_limit
. - The
emission_limit
time profiles cannot have a finer granulation thanStrategicProfile
. - The
emission_price
time profiles cannot have a finer granulation thanStrategicProfile
.
Conditional checks (if check_timeprofiles=true
)
- The profiles in
emission_limit
have to have the same length as the number of strategic periods. - The profiles in
emission_price
have to have the same length as the number of strategic periods.
EnergyModelsBase.check_node
— Functioncheck_node(n::Node, 𝒯, modeltype::EnergyModel)
Check that the fields of a Node
corresponds to required structure.
check_node(n::Availability, 𝒯, modeltype::EnergyModel)
This method checks that an Availability
node is valid. By default, that does not include any checks.
check_node(n::Source, 𝒯, modeltype::EnergyModel)
This method checks that a Source
node is valid.
These checks are always performed, if the user is not creating a new method. Hence, it is important that a new Source
type includes at least the same fields as in the RefSource
node or that a new Source
type receives a new method for check_node
.
Checks
- The field
cap
is required to be non-negative. - The values of the dictionary
output
are required to be non-negative. - The value of the field
fixed_opex
is required to be non-negative and accessible through aStrategicPeriod
as outlined in the functioncheck_fixed_opex(n, 𝒯ᴵⁿᵛ, check_timeprofiles)
.
check_node(n::NetworkNode, 𝒯, modeltype::EnergyModel)
This method checks that a NetworkNode
node is valid.
These checks are always performed, if the user is not creating a new method. Hence, it is important that a new NetworkNode
type includes at least the same fields as in the [RefNetworkNode
(@ref) node or that a new NetworkNode
type receives a new method for check_node
.
Checks
- The field
cap
is required to be non-negative. - The values of the dictionary
input
are required to be non-negative. - The values of the dictionary
output
are required to be non-negative. - The value of the field
fixed_opex
is required to be non-negative and accessible through aStrategicPeriod
as outlined in the functioncheck_fixed_opex(n, 𝒯ᴵⁿᵛ, check_timeprofiles)
.
check_node(n::Storage, 𝒯, modeltype::EnergyModel)
This method checks that a Storage
node is valid.
These checks are always performed, if the user is not creating a new method. Hence, it is important that a new Storage
type includes at least the same fields as in the RefStorage
node or that a new Storage
type receives a new method for check_node
.
Checks
- The
TimeProfile
of the fieldcapacity
in the type in the fieldcharge
is required to be non-negative if the chosen composite type has the fieldcapacity
. - The
TimeProfile
of the fieldcapacity
in the type in the fieldlevel
is required to be non-negative`. - The
TimeProfile
of the fieldcapacity
in the type in the fielddischarge
is required to be non-negative if the chosen composite type has the fieldcapacity
. - The
TimeProfile
of the fieldfixed_opex
is required to be non-negative and accessible through aStrategicPeriod
as outlined in the functioncheck_fixed_opex(n, 𝒯ᴵⁿᵛ, check_timeprofiles)
for the chosen composite type . - The values of the dictionary
input
are required to be non-negative. - The values of the dictionary
output
are required to be non-negative.
check_node(n::Sink, 𝒯, modeltype::EnergyModel)
This method checks that a Sink
node is valid.
These checks are always performed, if the user is not creating a new method. Hence, it is important that a new Sink
type includes at least the same fields as in the RefSink
node or that a new Source
type receives a new method for check_node
.
Checks
- The field
cap
is required to be non-negative. - The values of the dictionary
input
are required to be non-negative. - The dictionary
penalty
is required to have the keys:deficit
and:surplus
. - The sum of the values
:deficit
and:surplus
in the dictionarypenalty
has to be non-negative to avoid an infeasible model.
EnergyModelsBase.check_fixed_opex
— Functioncheck_fixed_opex(n, 𝒯ᴵⁿᵛ, check_timeprofiles::Bool)
Checks that the fixed opex value follows the given TimeStructure
. This check requires that a function opex_fixed(n)
is defined for the input n
which returns a TimeProfile
.
Checks
- The
opex_fixed
time profile cannot have a finer granulation thanStrategicProfile
.
Conditional checks (if check_timeprofiles=true
)
- The profiles in
opex_fixed
have to have the same length as the number of strategic periods.
EnergyModelsBase.check_node_data
— Methodcheck_node_data(n::Node, data::Data, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
check_node_data(n::Node, data::EmissionsData, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
Check that the included Data
types of a Node
corresponds to required structure. This function will always result in a multiple error message, if several instances of the same supertype is loaded.
Checks EmissionsData
- Each node can only have a single
EmissionsData
. - Time profiles for process emissions, if present.
- The value of the field
co2_capture
is required to be in the range $[0, 1]$, ifCaptureData
is used.
EnergyModelsBase.check_time_structure
— Functioncheck_time_structure(n::Node, 𝒯)
Check that all fields of a Node
that are of type TimeProfile
correspond to the time structure 𝒯
.
EnergyModelsBase.check_profile
— Functioncheck_profile(fieldname, value::TimeProfile, 𝒯)
Check that an individual TimeProfile
corresponds to the time structure 𝒯
. It currently does not include support for identifying OperationalScenarios
.
check_profile(fieldname, value::TimeProfile, ts::TimeStructure, sp)
Check that an individual TimeProfile
corresponds to the time structure ts
in strategic period sp
. The function flow is designed to provide errors in all situations in which the the TimeProfile
does not correspond to the chosen TimeStructure
through the application of the @assert_or_log
macro.
Examples for inconsistent combinations:
ts = SimpleTimes(3, 1)
# A too long OperationalProfile resulting in omitting the last 2 values
value = OperationalProfile([1, 2, 3, 4, 5])
# A too short OperationalProfile resulting in repetition of the last value once
value = OperationalProfile([1, 2])
If you use a more detailed TimeProfile than the TimeStructure, it will you provide you with a warning, e.g., using RepresentativeProfile
without RepresentativePeriods
.
It currently does not include support for identifying OperationalProfile
s.
EnergyModelsBase.check_strategic_profile
— Functioncheck_strategic_profile(time_profile::TimeProfile, message::String)
Function for checking that an individual TimeProfile
does not include the wrong type for strategic indexing.
Checks
TimeProfile
s accessed inStrategicPeriod
s cannot includeOperationalProfile
,ScenarioProfile
, orRepresentativeProfile
as this is not allowed through indexing on theTimeProfile
.
EnergyModelsBase.check_representative_profile
— Functioncheck_representative_profile(time_profile::TimeProfile, message::String)
Function for checking that an individual TimeProfile
does not include the wrong type for representative periods indexing.
Input
time_profile
- The time profile that should be checked.message
- A message that should be printed after the type of profile.
Checks
TimeProfile
s accessed inRepresentativePeriod
s cannot includeOperationalProfile
orScenarioProfile
as this is not allowed through indexing on theTimeProfile
.
EnergyModelsBase.check_scenario_profile
— Functioncheck_scenario_profile(time_profile::TimeProfile, message::String)
Function for checking that an individual TimeProfile
does not include the wrong type for scenario indexing.
Checks
TimeProfile
s accessed inRepresentativePeriod
s cannot includeOperationalProfile
orScenarioProfile
as this is not allowed through indexing on theTimeProfile
.
EnergyModelsBase.compile_logs
— Functioncompile_logs(case, log_by_element)
Simple method for showing all log messages.
Identification functions
EnergyModelsBase.is_network_node
— Functionis_network_node(n::Node)
Checks whether node n
is a NetworkNode
node.
EnergyModelsBase.is_sink
— Functionis_sink(n::Node)
Checks whether node n
is a Sink
node.
EnergyModelsBase.is_source
— Functionis_source(n::Node)
Checks whether node n
is a Source
node.
EnergyModelsBase.is_storage
— Functionis_storage(n::Node)
Checks whether node n
is a Storage
node.
EnergyModelsBase.is_resource_emit
— Functionis_resource_emit(p::Resource)
Checks whether the Resource p
is of type ResourceEmit
.
EnergyModelsBase.has_charge_OPEX_fixed
— Functionhas_charge_OPEX_fixed(n::Storage)
Returns logic whether the node has a charge
fixed OPEX contribution.
EnergyModelsBase.has_charge_OPEX_var
— Functionhas_charge_OPEX_var(n::Storage)
Returns logic whether the node has a charge
variable OPEX contribution.
EnergyModelsBase.has_charge_cap
— Functionhas_charge_cap(n::Storage)
Returns logic whether the node has a charge
capacity.
EnergyModelsBase.has_discharge_OPEX_fixed
— Functionhas_discharge_OPEX_fixed(n::Storage)
Returns logic whether the node has a discharge
fixed OPEX contribution.
EnergyModelsBase.has_discharge_OPEX_var
— Functionhas_discharge_OPEX_var(n::Storage)
Returns logic whether the node has a discharge
variable OPEX contribution.
EnergyModelsBase.has_discharge_cap
— Functionhas_discharge_cap(n::Storage)
Returns logic whether the node has a discharge
capacity.
EnergyModelsBase.has_level_OPEX_fixed
— Functionhas_level_OPEX_fixed(n::Storage)
Returns logic whether the node has a level
fixed OPEX contribution.
EnergyModelsBase.has_level_OPEX_var
— Functionhas_level_OPEX_var(n::Storage)
Returns logic whether the node has a level
variable OPEX contribution.
EnergyModelsBase.nodes_not_av
— Functionnodes_not_av(𝒩::Array{<:Node})
Returns nodes that are not Availability
nodes for a given Array 𝒩::Array{<:Node}
.
EnergyModelsBase.nodes_not_sub
— Functionnodes_not_sub(𝒩::Array{<:Node}, sub)
Returns nodes that are not of type sub
for a given Array 𝒩::Array{<:Node}
.
EnergyModelsBase.nodes_sub
— Functionnodes_sub(𝒩::Array{<:Node}, sub)
Returns nodes that are of type sub
for a given Array 𝒩::Array{<:Node}
.
EnergyModelsBase.link_res
— Functionlink_res(l::Link)
Return the resources transported for a given link l
.
EnergyModelsBase.link_sub
— Functionlink_sub(ℒ::Vector{<:Link}, n::Node)
Return connected links from the vector ℒ
for a given node n
as array. The first subarray corresponds to the from
field, while the second to the to
field.
EnergyModelsBase.res_em
— Functionres_em(𝒫::Array{<:Resource})
res_em(𝒫::Dict)
Returns all emission resources for a
- a given array
::Array{<:Resource}
. The output is in this case anArray{<:Resource}
- a given dictionary
::Dict
. The output is in this case a dictionaryDict
with the correct fields
EnergyModelsBase.res_not
— Functionres_not(𝒩::Array{<:Resource}, res_inst)
res_not(𝒫::Dict, res_inst::Resource)
Return all resources that are not res_inst
for
- a given array
::Array{<:Resource}
. The output is in this case anArray{<:Resource}
- a given dictionary
::Dict
. The output is in this case a dictionaryDict
with the correct fields
EnergyModelsBase.res_sub
— Functionres_sub(𝒫::Array{<:Resource}, sub = ResourceEmit)
Return resources that are of type sub
for a given Array ::Array{Resource}
.
Miscellaneous functions
EnergyModelsBase.collect_types
— Functioncollect_types(types_list)
Return a Dict of all the give types_list and their supertypes. The keys in the dictionary are the types, and their corresponding value is the number in the type hierarchy.
As an example, Node
is at the top and will thus have the value 1. Types just below Node
will have value 2, and so on.
EnergyModelsBase.sort_types
— Functionsort_types(types_list::Dict)
Sort the result of collect_types
and return a vector where a supertype comes before all its subtypes.