Public interface
Module
EnergyModelsBase
— ModuleMain module for EnergyModelsBase
a framework for building flexible energy system models.
It exports several types and associated functions for accessing fields. In addition, all required functions for creaeting and running the model are exported.
You can find the exported types and functions below or on the pages Constraint functions and Data functions.
Resources
Resource
s correspond to the mass/energy that is converted or transported within an energy system. Resource
s are discrete, that is they do not have as default additional variables, e.g. pressure or temperature, associated with them. Instead, they are implemented through flows and levels, as explained in Optimization variables.
Resource
types
The following resources are implemented in EnergyModelsBase
. EnergyModelsBase
differentiates between ResourceCarrier
and ResourceEmit
resources. The key difference between both is that ResourceEmit
resources can have emissions, e.g., CO₂ or methane. Emissions are accounted for and can have either a cap and/or a price associated with them.
One important field for a resource is the CO₂ intensity (co2_int
). CO₂ is handled differently than other emissions as the emissions are fundamental properties of a fuel based on the carbon content.
EnergyModelsBase.Resource
— TypeGeneral resource supertype to be used for the declaration of subtypes.
EnergyModelsBase.ResourceCarrier
— TypeResourceCarrier{T<:Real} <: Resource
Resources that can be transported and converted. These resources cannot be included as resources that are emitted, e.g, in the variable emissions_strategic
.
Fields
id
is the name/identifyer of the resource.co2_int::T
is the the CO₂ intensity, e.g., t/MWh.
EnergyModelsBase.ResourceEmit
— TypeResourceEmit{T<:Real} <: Resource
Resources that can can be emitted (e.g., CO₂, CH₄, NOₓ).
These resources can be included as resources that are emitted, e.g, in the variable emissions_strategic
.
Fields
id
is the name/identifyer of the resource.co2_int::T
is the the CO₂ intensity, e.g., t/MWh.
Functions for accessing fields of Resource
types
The following functions are declared for accessing fields from a Resource
type. If you want to introduce new Resource
types, it is important that this function are either functional for your new types or you have to declare a corresponding function.
EnergyModelsBase.co2_int
— Functionco2_int(p::Resource)
Returns the CO₂ intensity of resource p
Nodes
Node
s are used in EnergyModelsBase
to convert Resource
s. They are coupled to the rest of the system through the Flow variables. Nodes are the key types for extending EnergyModelsBase
through dispatch. You can find an introduction of the different node types on the page Creating a new node
Abstract Node
types
The following abstract node types are implemented in the EnergyModelsBase
. These abstract types are relevant for dispatching in individual functions.
EnergyModelsBase.Source
— TypeSource
node with only output.
EnergyModelsBase.NetworkNode
— TypeNetworkNode
node with both input and output.
EnergyModelsBase.Sink
— TypeSink
node with only input.
EnergyModelsBase.Storage
— TypeStorage
node with level.
EnergyModelsBase.Availability
— TypeAvailability
node as routing node.
Reference node types
The following composite types are implemented in the EnergyModelsBase
. They can be used for describing a simple energy system without any non-linear or binary based expressions. Hence, there are, e.g., no operation point specific efficiencies implemented.
EnergyModelsBase.RefSource
— TypeRefSource <: Source
A reference Source
node. The reference Source
node allows for a time varying capacity which is normalized to a conversion value of 1 in the field input
. Note, that if you include investments, you can only use as TimeProfile
a FixedProfile
or StrategicProfile
.
Fields
id
is the name/identifier of the node.cap::TimeProfile
is the installed capacity.opex_var::TimeProfile
is the variable operating expense per energy unit produced.opex_fixed::TimeProfile
is the fixed operating expense.output::Dict{<:Resource, <:Real}
are the generatedResource
s with conversion valueReal
.data::Vector{<:Data}
is the additional data (e.g. for investments). The fielddata
is conditional through usage of a constructor.
EnergyModelsBase.RefNetworkNode
— TypeRefNetworkNode <: NetworkNode
A reference NetworkNode
node. The RefNetworkNode
utilizes a linear, time independent conversion rate of the input
Resource
s to the output Resource
s, subject to the available capacity. The capacity is hereby normalized to a conversion value of 1 in the fields input
and output
.
Fields
id
is the name/identifier of the node.cap::TimeProfile
is the installed capacity.opex_var::TimeProfile
is the variable operating expense per energy unit produced.opex_fixed::TimeProfile
is the fixed operating expense.input::Dict{<:Resource, <:Real}
are the inputResource
s with conversion valueReal
.output::Dict{<:Resource, <:Real}
are the generatedResource
s with conversion valueReal
.data::Vector{Data}
is the additional data (e.g. for investments). The fielddata
is conditional through usage of a constructor.
EnergyModelsBase.RefSink
— TypeRefSink <: Sink
A reference Sink
node. This node corresponds to a demand given by the field cap
. The penalties introduced in the field penalty
affect the variable OPEX for both a surplus and deficit.
Fields
id
is the name/identifier of the node.cap::TimeProfile
is the Demand.penalty::Dict{Any, TimeProfile}
are penalties for surplus or deficits. Requires the fields:surplus
and:deficit
.input::Dict{<:Resource, <:Real}
are the inputResource
s with conversion valueReal
.data::Vector{<:Data}
is the additional data (e.g. for investments). The fielddata
is conditional through usage of a constructor.
EnergyModelsBase.RefStorage
— TypeRefStorage{T} <: Storage{T}
A reference Storage
node.
This node is designed to store either a ResourceCarrier
or a ResourceEmit
. It is designed as a parametric type through the type parameter T
to differentiate between different cyclic behaviours. Note that the parameter T
is only used for dispatching, but does not carry any other information. Hence, it is simple to fast switch between different StorageBehavior
s.
The current implemented cyclic behaviours are CyclicRepresentative
, CyclicStrategic
, and AccumulatingEmissions
.
Fields
id
is the name/identifier of the node.charge::AbstractStorageParameters
are the charging parameters of theStorage
node. Depending on the chosen type, the charge parameters can include variable OPEX, fixed OPEX, and/or a capacity.level::AbstractStorageParameters
are the level parameters of theStorage
node. Depending on the chosen type, the charge parameters can include variable OPEX and/or fixed OPEX.stor_res::Resource
is the storedResource
.input::Dict{<:Resource, <:Real}
are the inputResource
s with conversion valueReal
.output::Dict{<:Resource, <:Real}
are the generatedResource
s with conversion valueReal
. Only relevant for linking and the storedResource
as the output value is not utilized in the calculations.data::Vector{<:Data}
is the additional data (e.g. for investments). The fielddata
is conditional through usage of a constructor.
EnergyModelsBase.GenAvailability
— TypeGenAvailability <: Availability
A reference Availability
node. The reference Availability
node solves the energy balance for all connected flows.
Fields
id
is the name/identifier of the node.inputs::Vector{<:Resource}
are the inputResource
s.output::Vector{<:Resource}
are the outputResource
s.
A constructor is provided so that only a single array can be provided with the fields:
id
is the name/identifier of the node.𝒫::Vector{<:Resource}
are the[
Resource`](@ref)s.
Storage behaviours
EnergyModelsBase
provides several different storage behaviours for calculating the level balance of a Storage
node. In general, the concrete storage behaviours are ready to use and should account for all eventualities.
EnergyModelsBase.Accumulating
— TypeAccumulating
as supertype for an accumulating storage level.
Accumulating storage behaviour implies that the change in the overall storage level in a strategic period can be both positive or negative.
Examples for potential usage of Accumulating
are CO₂ storages in which the CO₂ is permanently stored or multi year hydropower magazines.
EnergyModelsBase.AccumulatingEmissions
— TypeAccumulatingEmissions <: Accumulating
StorageBehavior
which accumulates all inflow witin a strategic period. AccumulatingEmissions
allows as well to serve as a ResourceEmit
emission point to represent a soft constraint on storing the captured emissions.
EnergyModelsBase.Cyclic
— TypeCyclic
as supertype for a cyclic storage level.
Cyclic storage behaviour implies that the change in the overall storage level in a strategic period behaves cyclic.
EnergyModelsBase.CyclicRepresentative
— TypeCyclicRepresentative <: Cyclic
StorageBehavior
in which cyclic behaviour is achieved within the lowest time structure excluding operational times.
In the case of TwoLevel{SimpleTimes}
, this approach is similar to CyclicStrategic
. In the case of TwoLevel{RepresentativePeriods{SimpleTimes}}
, this approach differs from CyclicStrategic
as the cyclic constraint is enforeced within each representative period.
EnergyModelsBase.CyclicStrategic
— TypeCyclicStrategic <: Cyclic
StorageBehavior
in which the the cyclic behaviour is achieved within a strategic period. This implies that the initial level in individual representative periods can be different when using RepresentativePeriods
.
We have not yet supported upper and lower bound constraints in the case of using OperationalScenarios
. While the calculation of the overall level balance and the operational costs is consistent, it can happen that the upper and lower bound of the storage level is violated.
This impacts specifically CyclicStrategic
.
Storage parameters
Storage parameters are used for describing different parameters for the idnividual capacities of a Storage
node. In practice, Storage
nodes can have three different capacities:
- charge, that is a capacity for charging the
Storage
node, - level, that is the amount of energy/mass that can be stored, and
- discharge, that is a capacity for discharging the
Storage
node.
In general, each of the individual capacities can have an assigned capacity, variable OPEX, and fixed OPEX. Furthermore, it is possible to only have a variable OPEX. To this end, multiple composite types are defined.
EnergyModelsBase.StorCapOpex
— TypeStorCapOpex <: AbstractStorageParameters
A storage parameter type for including a capacity as well as variable and fixed operational expenditures.
Fields
capacity::TimeProfile
is the installed capacity.opex_var::TimeProfile
is the variable operating expense per energy unit.opex_fixed::TimeProfile
is the fixed operating expense.
EnergyModelsBase.StorCap
— TypeStorCap <: AbstractStorageParameters
A storage parameter type for including only a capacity. This implies that neither the usage of the Storage
, nor the installed capacity have a direct impact on the objective function.
Fields
capacity::TimeProfile
is the installed capacity.
EnergyModelsBase.StorCapOpexVar
— TypeStorCap <: AbstractStorageParameters
A storage parameter type for including a capacity and variable operational expenditures. This implies that the installed capacity has no direct impact on the objective function.
Fields
capacity::TimeProfile
is the installed capacity.opex_var::TimeProfile
is the variable operating expense per energy unit.
EnergyModelsBase.StorCapOpexFixed
— TypeStorCapOpexFixed <: AbstractStorageParameters
A storage parameter type for including a capacity and fixed operational expenditures. This implies that the installed capacity has no direct impact on the objective function.
Fields
capacity::TimeProfile
is the installed capacity.opex_fixed::TimeProfile
is the fixed operating expense.
EnergyModelsBase.StorOpexVar
— TypeStorCap <: AbstractStorageParameters
A storage parameter type for including variable operational expenditures. This implies that the charge or discharge rate do not have a capacity and the Storage
level can be used within a single TimePeriod
.
This type can only be used for the fields charge
and discharge
.
Fields
opex_var::TimeProfile
is the variable operating expense per energy unit.
When dispatching on the individual type, it is also possible to use the following unions:
EnergyModelsBase.UnionOpexFixed
— TypeUnionOpexFixed
Union for simpler dispatching for storage parameters that include fixed OPEX.
EnergyModelsBase.UnionOpexVar
— TypeUnionOpexVar
Union for simpler dispatching for storage parameters that include variable OPEX.
EnergyModelsBase.UnionCapacity
— TypeUnionCapacity
Union for simpler dispatching for storage parameters that include a capacity.
Functions for accessing fields of Node
types
The following functions are declared for accessing fields from a Node
type.
If you want to introduce new Node
types, it is important that these functions are either functional for your new types or you have to declare corresponding functions. The first approach can be achieved through using the same name for the respective fields.
The functions storage_resource
is only required for Storage
nodes, when you plan to use the implemented constraint function constraints_flow_in
. The functions surplus_penalty
and deficit_penalty
are only required for Sink
nodes if you plan to use the implemented constraint function constraints_opex_var
.
EnergyModelsBase.capacity
— Functioncapacity(n::Node)
Returns the capacity of a node n
as TimeProfile
. The capacity is not directly defined for Storage
nodes. Instead, it is necessary to call the function on the respective field, see capacity(stor_par::AbstractStorageParameters)
.
capacity(stor_par::AbstractStorageParameters)
Returns the capacity of storage parameter stor_par
as TimeProfile
. The individual storage parameters of a Storage
node can be accessed through the functions charge(n)
, level(n)
, and discharge(n)
.
capacity(n::Node, t)
Returns the capacity of a node n
at operational period t
. The capacity is not directly defined for Storage
nodes. Instead, it is necessary to call the function on the respective field, see capacity(stor_par::AbstractStorageParameters, t)
.
capacity(stor_par::AbstractStorageParameters, t)
Returns the capacity of storage parameter stor_par
at operational period t
. The individual storage parameters of a Storage
node can be accessed through the functions charge(n)
, level(n)
, and discharge(n)
.
EnergyModelsBase.opex_var
— Functionopex_var(n::Node)
Returns the variable OPEX of a node n
as TimeProfile
. The variable OPEX is not directly defined for Storage
nodes. Instead, it is necessary to call the function on the respective field, see opex_var(stor_par::AbstractStorageParameters)
.
opex_var(stor_par::UnionOpexVar)
Returns the variable OPEX of storage parameter stor_par
as TimeProfile
. The individual storage parameters of a Storage
node can be accessed through the functions charge(n)
, level(n)
, and discharge(n)
.
opex_var(n::Node, t)
Returns the variable OPEX of a node n
in operational period t
. The variable OPEX is not directly defined for Storage
nodes. Instead, it is necessary to call the function on the respective field, see opex_var(stor_par::AbstractStorageParameters, t)
.
opex_var(stor_par::UnionOpexVar, t)
Returns the variable OPEX of storage parameter stor_par
at operational period t
. The individual storage parameters of a Storage
node can be accessed through the functions charge(n)
, level(n)
, and discharge(n)
.
EnergyModelsBase.opex_fixed
— Functionopex_fixed(n::Node)
Returns the fixed OPEX of a node n
as TimeProfile
. The fixed OPEX is not directly defined for Storage
nodes. Instead, it is necessary to call the function on the respective field, see opex_fixed(stor_par::AbstractStorageParameters)
.
opex_fixed(stor_par::UnionOpexFixed)
Returns the fixed OPEX of storage parameter stor_par
as TimeProfile
. The individual storage parameters of a Storage
node can be accessed through the functions charge(n)
, level(n)
, and discharge(n)
.
opex_fixed(n::Node, t_inv)
Returns the fixed OPEX of a node n
at strategic period t_inv
. The fixed OPEX is not directly defined for Storage
nodes. Instead, it is necessary to call the function on the respective field, see opex_fixed(stor_par::AbstractStorageParameters, t)
.
opex_fixed(stor_par::UnionOpexFixed, t)
Returns the fixed OPEX of storage parameter stor_par
at operational period t
. The individual storage parameters of a Storage
node can be accessed through the functions charge(n)
, level(n)
, and discharge(n)
.
EnergyModelsBase.inputs
— Functioninputs(n::Node)
Returns the input resources of a node n
. These resources are specified via the field input
.
inputs(n::Node, p::Resource)
Returns the value of an input resource p
of a node n
.
EnergyModelsBase.outputs
— Functionoutputs(n::Node)
Returns the output resources of a node n
. These resources are specified via the field output
.
outputs(n::Node, p::Resource)
Returns the value of an output resource p
of a node n
.
EnergyModelsBase.node_data
— Functionnode_data(n::Node)
Returns the Data
array of node n
.
EnergyModelsBase.charge
— Functioncharge(n::Storage)
Returns the parameter type of the charge
field of the node. If the node has no field charge
, it returns nothing
.
EnergyModelsBase.level
— Functionlevel(n::Storage)
Returns the parameter type of the level
field of the node.
EnergyModelsBase.discharge
— Functiondischarge(n::Storage)
Returns the parameter type of the discharge
field of the node. If the node has no field discharge
, it returns nothing
.
EnergyModelsBase.storage_resource
— Functionstorage_resource(n::Storage)
Returns the storage resource of Storage
node n
.
EnergyModelsBase.surplus_penalty
— Functionsurplus_penalty(n::Sink)
Returns the surplus penalty of sink n
as TimeProfile
.
surplus_penalty(n::Sink, t)
Returns the surplus penalty of sink n
at operational period t
EnergyModelsBase.deficit_penalty
— Functiondeficit_penalty(n::Sink)
Returns the deficit penalty of sink n
as TimeProfile
.
deficit_penalty(n::Sink, t)
Returns the deficit penalty of sink n
at operational period t
Functions for identifying Node
s
The following functions are declared for filtering on Node
types.
If you want to introduce new Node
types, it is important that the functions has_input
, has_output
, and has_emissions
are either functional for your new types or you have to declare corresponding functions. The first approach can be achieved through using the same name for the respective fields.
The functions nodes_input
, nodes_output
, and nodes_emissions
are not used in the model as they are replaced by the build in filter function as, e.g., filter(has_input, 𝒩)
. In practice, they provide a pre-defined approach for filtering nodes and do not require additional modifications. They can be used in potential extensions.
EnergyModelsBase.nodes_input
— Functionnodes_input(𝒩::Array{<:Node}, sub)
Returns nodes that have an input, i.e., Sink
and NetworkNode
nodes.
EnergyModelsBase.nodes_output
— Functionnodes_output(𝒩::Array{<:Node})
Returns nodes that have an output, i.e., Source
and NetworkNode
nodes.
EnergyModelsBase.nodes_emissions
— Functionhas_emissions(𝒩::Array{<:Node})
Returns nodes that have emission data for a given Array ::Array{<:Node}
.
EnergyModelsBase.has_input
— Functionhas_input(n::Node)
Returns logic whether the node is an input node, i.e., Sink
and NetworkNode
nodes.
EnergyModelsBase.has_output
— Functionhas_output(n::Node)
Returns logic whether the node is an output node, i.e., Source
and NetworkNode
nodes.
EnergyModelsBase.has_emissions
— Functionhas_emissions(n::Node)
Checks whether the Node n
has emissions.
EnergyModelsBase.has_charge
— Functionhas_charge(n::Storage)
Returns logic whether the node has a charge
field allowing for restrictions and/or costs on the (installed) charging rate.
EnergyModelsBase.has_discharge
— Functionhas_discharge(n::Storage)
Returns logic whether the node has a discharge
field allowing for restrictions and/or costs on the (installed) discharging rate.
Links
Link
s are connecting the individual Node
s for the exchange of energy/mass. Link
s are directional, that is transport of mass/energy is only allowed in a single direction.
Link
types
The following types for links are implemented in EnergyModelsBase
. The thought process is to dispatch on the EMB.Formulation
of a link as additional option. This is in the current stage not implemented.
EnergyModelsBase.Link
— TypeDeclaration of the general type for links connecting nodes.
EnergyModelsBase.Direct
— TypeDirect <: Link
A direct link between two nodes.
Fields
id
is the name/identifier of the link.from::Node
is node from which there is flow into the link.to::Node
is node to which there is flow out of the link.formulation::Formulation
is the used formulation of links. If not specified, aLinear
link is assumed.
EnergyModelsBase.Linear
— TypeLinear Formulation
, that is input equals output.
Functions for accessing fields of Link
types
The following functions are declared for accessing fields from a Link
type.
If you want to introduce new Link
types, it is important that the function formulation
is either functional for your new types or you have to declare a corresponding function. The first approach can be achieved through using the same name for the respective fields.
EnergyModelsBase.formulation
— Functionformulation(l::Link)
Return the formulation of a Link ´l´.
Model and data
EnergyModel
and Data
types
The type EnergyModel
is used for creating the global parameters of a model. It can be as well used for extending EnergyModelsBase
as described in the section Extensions to the model. EnergyModelsBase
provides an OperationalModel
for analyses with given capacities. OperationalModel
contains some key information for the model such as the emissions limits and penalties for each ResourceEmit
, as well as the ResourceEmit
instance of CO₂.
Including the extension EnergyModelsInvestments
results in the declaration of the types AbstractInvestmentModel
and InvestmentModel
which can be used for creating models with investments It takes as additional input the discount_rate
. The discount_rate
is an important element of investment analysis needed to represent the present value of future cash flows. It is provided to the model as a value between 0 and 1 (e.g. a discount rate of 5 % is 0.05).
EnergyModelsBase.EnergyModel
— TypeAbstract type for differentation between types of models (investment, operational, ...).
EnergyModelsBase.OperationalModel
— TypeOperationalModel <: EnergyModel
Operational Energy Model without investments.
Fields
emission_limit::Dict{<:ResourceEmit, <:TimeProfile}
is a dictionary with individual emission limits asTimeProfile
for each emission resourceResourceEmit
.emission_price::Dict{<:ResourceEmit, <:TimeProfile}
are the prices for the different considered emission resourcesResourceEmit
.co2_instance
is aResourceEmit
and corresponds to the type used for CO₂.
EnergyModelsBase.AbstractInvestmentModel
— TypeAbstractInvestmentModel <: EnergyModel
An abstract investment model type.
This abstract model type should be used when creating additional EnergyModel
types that should utilize investments.
An example for additional types is given by the inclusion of, e.g., SDDP
.
EnergyModelsBase.InvestmentModel
— TypeInvestmentModel <: AbstractInvestmentModel
A concrete basic investment model type based on the standard OperationalModel
. The concrete basic investment model is similar to an OperationalModel
, but allows for investments and additional discounting of future years.
Fields
emission_limit::Dict{<:ResourceEmit, <:TimeProfile}
are the emission caps for the different emissions types considered.emission_price::Dict{<:ResourceEmit, <:TimeProfile}
are the prices for the different emissions types considered.co2_instance
is aResourceEmit
and corresponds to the type used for CO₂.r::Float64
is the discount rate in the investment optimization.
In addition, the following Data
types are introduced for introducing additional parameters, variables, and constraints to the Node
s. The approach of using the data
field of Node
s is explained on the page Data functions. EmptyData
is no longer relevant for the modelling, but it is retained for avoiding any problems with existing models.
EnergyModelsBase.Data
— TypeAbstract type used to define concrete struct containing the package specific elements to add to the composite type defined in this package.
EnergyModelsBase.EmptyData
— TypeEmpty composite type for Data
Functions for accessing fields of EnergyModel
types
The following functions are declared for accessing fields from a EnergyModel
type.
If you want to introduce new EnergyModel
types, it is important that the functions emission_limit
, emission_price
, and co2_instance
are either functional for your new types or you have to declare corresponding functions. The first approach can be achieved through using the same name for the respective fields.
If you want to introduce new AbstractInvestmentModel
types, you have to in additional consider the function discount_rate
.
EnergyModelsBase.emission_limit
— Functionemission_limit(modeltype::EnergyModel)
Returns the emission limit of EnergyModel model
as dictionary with TimeProfile
s for each ResourceEmit
.
emission_limit(modeltype, p::ResourceEmit)
Returns the emission limit of EnergyModel model
and ResourceEmit
p
as TimeProfile
.
emission_limit(modeltype, p::ResourceEmit, t_inv::TS.StrategicPeriod)
Returns the emission limit of EnergyModel model
and ResourceEmit
p
in strategic period period t_inv
.
EnergyModelsBase.emission_price
— Functionemission_price(modeltype::EnergyModel)
Returns the emission price of EnergyModel model
as dictionary with TimeProfile
s for each ResourceEmit
.
emission_price(modeltype, p::ResourceEmit)
Returns the emission price of EnergyModel modeltype
and ResourceEmit p
as TimeProfile
. If no emission price is specified for the ResourceEmit p
, the function returns 0
emission_price(modeltype, p::ResourceEmit, t_inv::TS.StrategicPeriod)
Returns the emission price of EnergyModel modeltype
and ResourceEmit p
in strategic period t_inv
. If no emission price is specified for the ResourceEmit p
, the function returns 0
EnergyModelsBase.co2_instance
— Functionco2_instance(modeltype::EnergyModel)
Returns the CO₂ instance used in modelling.
EnergyModelsBase.discount_rate
— Functiondiscount_rate(modeltype::AbstractInvestmentModel)
Returns the discount rate of AbstractInvestmentModel
modeltype.
Functions for running the model
The following functions are provided for both creating a model using EnergyModelsBase
and solving said model. Both functions have the input case
and model
. run_model
calls create_model
in the function, hence, it is not necessary to call the function beforehand.
The case
dictionary has to follow a certain outline. In this case, it is simplest to look at the provided examples.
We are currently debating to replace the dictionary used for case
as well with a composite type.
This will lead to breacking changes, but should be simple to adjust for.
EnergyModelsBase.create_model
— Functioncreate_model(case, modeltype::EnergyModel, m::JuMP.Model; check_timeprofiles::Bool=true)
Create the model and call all required functions.
Input
case
- The case dictionary requiring the keys:T
,:nodes
,:links
, andproducts
. If the input is not provided in the correct form, the checks will identify the problem.modeltype
- Used modeltype, that is a subtype of the typeEnergyModel
.m
- the emptyJuMP.Model
instance. If it is not provided, then it is assumed that the input is a standardJuMP.Model
.
Conditional input
check_timeprofiles=true
- A boolean indicator whether the time profiles of the individual nodes should be checked or not. It is advised to not deactivate the check, except if you are testing new components. It may lead to unexpected behaviour and potential inconsistencies in the input data, if the time profiles are not checked.
EnergyModelsBase.run_model
— Functionrun_model(case::Dict, model::EnergyModel, optimizer)
Take the case
data as a dictionary and the model
and build and optimize the model. Returns the solved JuMP model.
The dictionary requires the keys:
:nodes::Vector{Node}
:links::Vector{Link}
:products::Vector{Resource}
:T::TimeStructure
Functions for extending the model
The following functions are used for developing new nodes. See the page Creating a new node for a detailed explanation on how to create a new node.
EnergyModelsBase.variables_node
— Function" variables_node(m, 𝒩ˢᵘᵇ::Vector{<:Node}, 𝒯, modeltype::EnergyModel)
Default fallback method when no function is defined for a node type.
variables_node(m, 𝒩ˢⁱⁿᵏ::Vector{<:Sink}, 𝒯, modeltype::EnergyModel)
Declaration of both surplus (:sink_surplus
) and deficit (:sink_deficit
) variables for Sink
nodes 𝒩ˢⁱⁿᵏ
to quantify when there is too much or too little energy for satisfying the demand.
EnergyModelsBase.create_node
— Functioncreate_node(m, n::Source, 𝒯, 𝒫, modeltype::EnergyModel)
Set all constraints for a Source
. Can serve as fallback option for all unspecified subtypes of Source
.
create_node(m, n::NetworkNode, 𝒯, 𝒫, modeltype::EnergyModel)
Set all constraints for a NetworkNode
. Can serve as fallback option for all unspecified subtypes of NetworkNode
.
create_node(m, n::Storage, 𝒯, 𝒫, modeltype::EnergyModel)
Set all constraints for a Storage
. Can serve as fallback option for all unspecified subtypes of Storage
.
create_node(m, n::Sink, 𝒯, 𝒫, modeltype::EnergyModel)
Set all constraints for a Sink
. Can serve as fallback option for all unspecified subtypes of Sink
.
create_node(m, n::Availability, 𝒯, 𝒫, modeltype::EnergyModel)
Set all constraints for a Availability
. Can serve as fallback option for all unspecified subtypes of Availability
.
Availability nodes can be seen as routing nodes. It is not necessary to have more than one available node except if one wants to include as well transport between different Availability
nodes with associated costs (not implemented at the moment).
Constraint functions
The following functions can be used in new developed nodes to include constraints. See the pages Constraint functions and Data functions for a detailed explanation on their usage.
The function constraints_capacity_installed
should not be changed. It is used for the inclusion of investments through EnergyModelsInvestments
. It also has to be called, if you create a new function constraints_capacity
.
EnergyModelsBase.constraints_flow_in
— Functionconstraints_flow_in(m, n, 𝒯::TimeStructure, modeltype::EnergyModel)
Function for creating the constraint on the inlet flow to a generic Node
. This function serves as fallback option if no other function is specified for a Node
.
constraints_flow_in(m, n::Storage, 𝒯::TimeStructure, modeltype::EnergyModel)
Function for creating the constraint on the inlet flow to a generic Storage
. This function serves as fallback option if no other function is specified for a Storage
.
constraints_flow_in(m, n::Storage, 𝒯::TimeStructure, modeltype::EnergyModel)
Create the constraint on the inlet flow to a generic Storage
. This function serves as fallback option if no other function is specified for a Storage
.
EnergyModelsBase.constraints_flow_out
— Functionconstraints_flow_out(m, n::Node, 𝒯::TimeStructure, modeltype::EnergyModel)
Function for creating the constraint on the outlet flow from a generic Node
. This function serves as fallback option if no other function is specified for a Node
.
constraints_flow_out(m, n::Storage, 𝒯::TimeStructure, modeltype::EnergyModel)
Function for creating the constraint on the outlet flow from a generic Storage
. This function serves as fallback option if no other function is specified for a Storage
.
EnergyModelsBase.constraints_capacity
— Functionconstraints_capacity(m, n::Node, 𝒯::TimeStructure, modeltype::EnergyModel)
Function for creating the constraint on the maximum capacity of a generic Node
. This function serves as fallback option if no other function is specified for a Node
.
constraints_capacity(m, n::Storage, 𝒯::TimeStructure, modeltype::EnergyModel)
Function for creating the constraint on the maximum level of a generic Storage
. This function serves as fallback option if no other function is specified for a Storage
.
constraints_capacity(m, n::Sink, 𝒯::TimeStructure, modeltype::EnergyModel)
Function for creating the constraint on the maximum capacity of a generic Sink
. This function serves as fallback option if no other function is specified for a Sink
.
EnergyModelsBase.constraints_capacity_installed
— FunctionEMB.constraints_capacity_installed(
m,
n::EMB.Node,
𝒯::TimeStructure,
modeltype::AbstractInvestmentModel,
)
When the modeltype is an investment model, the function introduces the related constraints for the capacity expansion. The investment mode and lifetime mode are used for adding constraints.
The default function only accepts nodes with SingleInvData
. If you have several capacities for investments, you have to dispatch specifically on the node type. This is implemented for Storage
nodes.
EMB.constraints_capacity_installed(
m,
n::Storages,
𝒯::TimeStructure,
modeltype::AbstractInvestmentModel,
)
When the modeltype is an investment model and the node is a Storage
node, the function introduces the related constraints for the capacity expansions for the fields :charge
, :level
, and :discharge
. This requires the utilization of the StorageInvData
investment type, in which the investment mode and lifetime mode are used for adding constraints for each capacity.
constraints_capacity_installed(m, n, 𝒯::TimeStructure, modeltype::EnergyModel)
Constrain the installed capacity to the available capacity.
This function should only be used to dispatch on the modeltype for providing investments. If you create new capacity variables, it is beneficial to include as well a method for this function and the corresponding node types.
EnergyModelsBase.constraints_level
— Functionconstraints_level(m, n::Storage, 𝒯, 𝒫, modeltype::EnergyModel)
Function for creating the level constraint for a reference storage node with a ResourceCarrier
resource.
EnergyModelsBase.constraints_level_aux
— Functionconstraints_level_aux(m, n::Storage, 𝒯, 𝒫, modeltype::EnergyModel)
Create the Δ constraint for the level of a reference storage node with a ResourceCarrier
resource.
constraints_level_aux(m, n::RefStorage{S}, 𝒯, 𝒫, modeltype::EnergyModel)
Function for creating the Δ constraint for the level of a reference storage node with a ResourceEmit
resource.
EnergyModelsBase.constraints_opex_var
— Functionconstraints_opex_var(m, n::Node, 𝒯ᴵⁿᵛ, modeltype::EnergyModel)
Function for creating the constraint on the variable OPEX of a generic Node
. This function serves as fallback option if no other function is specified for a Node
.
constraints_opex_var(m, n::Storage, 𝒯ᴵⁿᵛ, modeltype::EnergyModel)
Function for creating the constraint on the variable OPEX of a generic Storage
. This function serves as fallback option if no other function is specified for a Storage
.
constraints_opex_var(m, n::Sink, 𝒯ᴵⁿᵛ, modeltype::EnergyModel)
Function for creating the constraint on the variable OPEX of a generic Sink
. This function serves as fallback option if no other function is specified for a Sink
.
EnergyModelsBase.constraints_opex_fixed
— Functionconstraints_opex_fixed(m, n::Node, 𝒯ᴵⁿᵛ, modeltype::EnergyModel)
Function for creating the constraint on the fixed OPEX of a generic Node
. This function serves as fallback option if no other function is specified for a Node
.
constraints_opex_fixed(m, n::Storage, 𝒯ᴵⁿᵛ, modeltype::EnergyModel)
Function for creating the constraint on the fixed OPEX of a generic Storage
. This function serves as fallback option if no other function is specified for a Storage
.
The fallback option includes fixed OPEX for charge
, level
, and discharge
. The individual contributions are in all situations calculated based on the installed capacities.
constraints_opex_fixed(m, n::Sink, 𝒯ᴵⁿᵛ, modeltype::EnergyModel)
Function for creating the constraint on the fixed OPEX of a generic Sink
. This function serves as fallback option if no other function is specified for a Sink
.
EnergyModelsBase.constraints_data
— Functionconstraints_data(m, n::Node, 𝒯, 𝒫, modeltype::EnergyModel, data::DataEmissions)
Constraints functions for calculating both the emissions and amount of CO₂ captured in the process.
There exist several configurations:
EmissionsEnergy
: Only energy usage related emissions.EmissionsProcess
: Both process and energy usage related emissions.CaptureEnergyEmissions
: Capture of energy usage related emissions, can include process emissions.CaptureProcessEmissions
: Capture of process emissions.CaptureProcessEnergyEmissions
: Capture of both process and energy usage related
emissions.
constraints_data(m, n::Node, 𝒯, 𝒫, modeltype::EnergyModel, data::Data)
Fallback option when data is specified, but it is not desired to add the constraints through this function. This is, e.g., the case for EnergyModelsInvestments
as the capacity constraint has to be replaced
In addition, auxiliary functions are introduced for the calculation of the previous level of storage nodes. These auxiliary functions provide the user with simple approaches for calculating the level balances.
EnergyModelsBase.previous_level
— Functionprevious_level(
m,
n::Storage,
prev_pers::PreviousPeriods,
cyclic_pers::CyclicPeriods,
modeltype::EnergyModel,
)
Returns the level used as previous level of a Storage
node depending on the type of PreviousPeriods
.
The basic functionality is used in the case when the previous operational period is a TimePeriod
, in which case it just returns the previous operational period.
previous_level(
m,
n::Storage,
prev_pers::PreviousPeriods{<:NothingPeriod, Nothing, Nothing},
cyclic_pers::CyclicPeriods,
modeltype::EnergyModel,
)
When the previous operational and representative period are Nothing
, the function returns the cyclic constraints within a strategic period. This is achieved through calling a subfunction previous_level_sp
to avoid method ambiguities.
previous_level(
m,
n::Storage,
prev_pers::PreviousPeriods{<:NothingPeriod, Nothing, Nothing},
cyclic_pers::CyclicPeriods,
modeltype::EnergyModel,
)
When the previous operational and representative period are Nothing
and the storage node is an AccumulatingEmissions
storage node, the function returns a value of 0.
previous_level(
m,
n::Storage,
prev_pers::PreviousPeriods{<:NothingPeriod, <:TS.AbstractRepresentativePeriod, Nothing},
cyclic_pers::CyclicPeriods,
modeltype::EnergyModel,
)
When the previous operational period is Nothing
, the previous representative period an AbstractRepresentativePeriod
and the last period is an AbstractRepresentativePeriod
, then the time structure does include RepresentativePeriods
.
The cyclic default constraints returns the value at the end of the previous representative period while accounting for the number of repetitions of the representative period.
previous_level(
m,
n::Storage{CyclicRepresentative},
prev_pers::PreviousPeriods{<:NothingPeriod, <:TS.AbstractRepresentativePeriod, Nothing},
cyclic_pers::CyclicPeriods,
modeltype::EnergyModel,
)
When the previous operational period is Nothing
and the previous representative period an AbstractRepresentativePeriod
then the time structure does include RepresentativePeriods
.
The cyclic constraint for a CyclicRepresentative
storage nodereturns the value at the end of the current representative period.
EnergyModelsBase.previous_level_sp
— Functionprevious_level_sp(
m,
n::Storage{<:Cyclic},
cyclic_pers::CyclicPeriods,
modeltype
)
Returns the previous period in the case of the first operational period (in the first representative period) of a strategic period.
The default functionality in the case of a Cyclic
storage node in a TimeStructure
without RepresentativePeriods
returns the last operational period in the strategic period.
previous_level_sp(
m,
n::Storage{CyclicStrategic},
cyclic_pers::CyclicPeriods{<:TS.AbstractRepresentativePeriod},
modeltype::EnergyModel,
)
When a CyclicStrategic
Storage
node is coupled with a TimeStructure
containing RepresentativePeriods
, then the function calculates the level at the beginning of the first representative period through the changes in the level in the last representative period.
previous_level_sp(
m,
n::Storage{CyclicRepresentative},
cyclic_pers::CyclicPeriods{<:TS.AbstractRepresentativePeriod},
modeltype::EnergyModel,
)
When a CyclicRepresentative
Storage
node is coupled with a TimeStructure
containing RepresentativePeriods
, then the function returns the previous level as the level at the end of the current representative period.
Emission data
Emission data are used to provide the individual nodes with potential emissions. The approach is also explained on the page Data functions.
Emission
types
The thought process with EmissionData
is to provide the user with options for each individual node to include emissions and potentially capture or not. The individual types can be used for all included reference Node
s, although capture is not possible for Sink
nodes due to the lack of an output.
EnergyModelsBase.EmissionsData
— TypeEmissionsData
as supertype for all Data
types for emissions.
EnergyModelsBase.CaptureData
— TypeCaptureData
as supertype for all EmissionsData
that include CO₂ capture.
EnergyModelsBase.EmissionsEnergy
— TypeEmissionsEnergy{T} <: EmissionsData{T}
No capture, no process emissions are present. Does not require co2_capture
or emissions
as input, but accepts it and will ignore it, if provided.
EnergyModelsBase.EmissionsProcess
— TypeEmissionsProcess{T} <: EmissionsData{T}
No capture, but process emissions are present. Does not require co2_capture
as input, but accepts it and will ignore it, if provided.
Fields
emissions::Dict{ResourceEmit, T}
: emissions per unit produced.
EnergyModelsBase.CaptureEnergyEmissions
— TypeCaptureEnergyEmissions{T} <: CaptureData{T}
Capture the energy usage related emissions, but not the process emissions. Does not require emissions
as input, but can be supplied.
Fields
emissions::Dict{ResourceEmit, T}
are the process emissions per unit produced.co2_capture::Float64
is the CO₂ capture rate.
EnergyModelsBase.CaptureProcessEmissions
— TypeCaptureProcessEmissions{T} <: CaptureData{T}
Capture the process emissions, but not the energy usage related emissions.
Fields
emissions::Dict{ResourceEmit, T}
are the process emissions per unit produced.co2_capture::Float64
is the CO₂ capture rate.
EnergyModelsBase.CaptureProcessEnergyEmissions
— TypeCaptureProcessEnergyEmissions{T} <: CaptureData{T}
Capture both the process emissions and the energy usage related emissions.
Fields
emissions::Dict{ResourceEmit, T}
are the process emissions per unit produced.co2_capture::Float64
is the CO₂ capture rate.
Functions for accessing fields of EmissionsData
types
The following functions are declared for accessing fields from a EmissionsData
type.
If you want to introduce new EmissionsData
types, it is important that the functions co2_capture
and process_emissions
are either functional for your new types or you have to declare corresponding functions. The first approach can be achieved through using the same name for the respective fields.
EnergyModelsBase.co2_capture
— Functionco2_capture(data::CaptureData)
Returns the CO₂ capture rate of the data
.
EnergyModelsBase.process_emissions
— Functionprocess_emissions(data::EmissionsData)
Returns the ResourceEmit
s that have process emissions of the EmissionsData
.
process_emissions(data::EmissionsData{T}, p::ResourceEmit)
Returns the the process emissions of resource p
in the data
as TimeProfile
. If the process emissions are provided as Float64
, it returns a FixedProfile(x)
. If there are no process emissions, it returns a FixedProfile(0)
.
process_emissions(data::EmissionsData{T}, p:ResourceEmit, t)
Returns the the process emissions of resource p
in the data
at operational period t. If there are no process emissions, it returns a value of 0.
Investment data
InvestmentData
types
InvestmentData
subtypes are used to provide technologies introduced in EnergyModelsX
(nodes and transmission modes) a subtype of Data
that can be used for dispatching. Two different types are directly introduced, SingleInvData
and StorageInvData
.
SingleInvData
is providing a composite type with a single field. It is used for investments in technologies with a single capacity, that is all nodes except for storage nodes as well as tranmission modes.
StorageInvData
is required as Storage
nodes behave differently compared to the other nodes. In Storage
nodes, it is possible to invest both in the charge capacity for storing energy, the storage capacity, that is the level of a Storage
node, as well as the discharge capacity, that is how fast energy can be withdrawn. Correspondingly, it is necessary to have individual parameters for the potential investments in each capacity, that is through the fields :charge
, :level
, and :discharge
.
EnergyModelsBase.InvestmentData
— TypeAbstract type for the extra data for investing in technologies.
EnergyModelsBase.SingleInvData
— TypeSingleInvData <: InvestmentData
Extra investment data for type investments. The extra investment data has only a single field in which AbstractInvData
has to be added.
The advantage of separating AbstractInvData
from the InvestmentData
node is to allow easier separation of EnergyModelsInvestments
and EnergyModelsBase
and provides the user with the potential of introducing new capacities for types.
Fields
cap::AbstractInvData
is the investment data for the capacity.
When multiple inputs are provided, a constructor directly creates the corresponding AbstractInvData
.
Fields
capex::TimeProfile
is the capital costs for investing in a capacity. The value is relative to the added capacity.max_inst::TimeProfile
is the maximum installed capacity in a strategic period.initial::Real
is the initial capacity. This results in the creation of aStartInvData
type for the investment data.inv_mode::Investment
is the chosen investment mode for the technology. The following investment modes are currently available:BinaryInvestment
,DiscreteInvestment
,ContinuousInvestment
,SemiContinuousInvestment
, orFixedInvestment
.life_mode::LifetimeMode
is type of handling the lifetime. Several different alternatives can be used:UnlimitedLife
,StudyLife
,PeriodLife
, orRollingLife
. Iflife_mode
is not specified, the model assumes anUnlimitedLife
.
EnergyModelsBase.StorageInvData
— TypeStorageInvData <: InvestmentData
Extra investment data for storage investments. The extra investment data for storage investments can, but does not require investment data for the charge capacity of the storage (charge
), increasing the storage capacity (level
), or the discharge capacity of the storage (discharge
).
It utilizes a constructor with keyword arguments for the individual parameters. Hence, the names of the parameters have to be specified.
Fields
charge::Union{AbstractInvData, Nothing}
is the investment data for the charge capacity.level::Union{AbstractInvData, Nothing}
is the investment data for the level capacity.discharge::Union{AbstractInvData, Nothing}
is the investment data for the discharge capacity.
Legacy constructors
We provide a legacy constructor, InvData
and InvDataStorage
, that use the same input as in version 0.5.x. If you want to adjust your model to the latest changes, please refer to the section Update your model to the latest version of EnergyModelsInvestments.
EnergyModelsBase.InvData
— FunctionEMB.InvData(;kwargs)
Internal method for InvData
. The introduction of an internal method is necessary as extensions do not allow to export functions or types.
InvData(;
capex_cap::TimeProfile,
cap_max_inst::TimeProfile,
cap_max_add::TimeProfile,
cap_min_add::TimeProfile,
inv_mode::Investment = ContinuousInvestment(),
cap_start::Union{Real, Nothing} = nothing,
cap_increment::TimeProfile = FixedProfile(0),
life_mode::LifetimeMode = UnlimitedLife(),
lifetime::TimeProfile = FixedProfile(0),
)
Legacy constructor for a InvData
.
The new storage descriptions allows now for a reduction in functions which is used to make EnergModelsInvestments
less dependent on EnergyModelsBase
.
The core changes to the existing structure is the move of the required parameters to the type Investment
(e.g., the minimum and maximum added capacity is only required for investment modes that require these parameters) as well as moving the lifetime
to the type LifetimeMode
, when required.
See the documentation for further information regarding how you can translate your existing model to the new model.
EnergyModelsBase.InvDataStorage
— FunctionInvDataStorage(;kwargs)
Internal method for InvDataStorage
. The introduction of an internal method is necessary as extensions do not allow to export functions or types.
InvDataStorage(;
#Investment data related to storage power
capex_rate::TimeProfile,
rate_max_inst::TimeProfile,
rate_max_add::TimeProfile,
rate_min_add::TimeProfile,
capex_stor::TimeProfile,
stor_max_inst::TimeProfile,
stor_max_add::TimeProfile,
stor_min_add::TimeProfile,
inv_mode::Investment = ContinuousInvestment(),
rate_start::Union{Real, Nothing} = nothing,
stor_start::Union{Real, Nothing} = nothing,
rate_increment::TimeProfile = FixedProfile(0),
stor_increment::TimeProfile = FixedProfile(0),
life_mode::LifetimeMode = UnlimitedLife(),
lifetime::TimeProfile = FixedProfile(0),
)
Storage descriptions were changed in EnergyModelsBase v0.7 resulting in the requirement for rewriting the investment options for Storage
nodes.
See the documentation for further information regarding how you can translate your existing model to the new model.
Miscellaneous types/functions/macros
PreviousPeriods
and CyclicPeriods
PreviousPeriods
is a type used to store information from the previous periods in an iteration loop through the application of the iterator withprev
of TimeStruct
.
CyclicPeriods
is used for storing the current and the last period. The periods can either be either and AbstractStrategicPeriod
or AbstractRepresentativePeriod
. In the former case, it is however not fully used as the last strategic period is not relevant for the level balances.
Both composite types allow only EMB.NothingPeriod
types as input to the individual fields.
EnergyModelsBase.PreviousPeriods
— TypePreviousPeriods{S<:NothingPeriod, T<:NothingPeriod, U<:NothingPeriod}
Contains the previous strategic, representative, and operational period used through the application of the with_prev
iterator developed in TimeStruct
.
Fields
sp::S
the previous strategic period.rp::T
the previous representative period.op::U
the previous operational period.
EnergyModelsBase.CyclicPeriods
— TypeCyclicPeriods{S<:NothingPeriod}
Contains information for calculating the cyclic constraints. The parameter S
should be either an AbstractStrategicPeriod
or AbstractRepresentativePeriod
.
Fields
last_per::S
the last period in the case ofS<:AbstractRepresentativePeriod
or the current period in the case ofS<:AbstractStrategicPeriod
as the last strategic period is not relevant.current_per::S
the current period in both the case ofS<:AbstractRepresentativePeriod
andS<:AbstractStrategicPeriod
.
EnergyModelsBase.NothingPeriod
— TypeUnion of Nothing
, TS.TimePeriod
, and TS.TimeStructure{T} where {T}
to be used for limiting the potential entries to the fields of PreviousPeriods
and CyclicPeriods
types.
The individual fields can be accessed through the following functions:
EnergyModelsBase.strat_per
— Functionstrat_per(prev_periods::PreviousPeriods)
Extracts the previous strategic period (fields sp
) from a PreviousPeriods
type.
EnergyModelsBase.rep_per
— Functionrep_per(prev_periods::PreviousPeriods)
Extracts the previous representative period (fields sp
) from a PreviousPeriods
type.
EnergyModelsBase.op_per
— Functionop_per(prev_periods::PreviousPeriods)
Extracts the previous operational period (fields sp
) from a PreviousPeriods
type.
EnergyModelsBase.last_per
— Functionlast_per(cyclic_pers::CyclicPeriods)
Extracts the last period (fields last_per
) from a CyclicPeriods
type.
EnergyModelsBase.current_per
— Functioncurrent_per(cyclic_pers::CyclicPeriods)
Extracts the current period (fields current_per
) from a CyclicPeriods
type.
Macros for checking the input data
The macro @assert_or_log
is an extension to the @assert
macro to allow either for asserting the input data directly, or logging the errors in the input data.
EnergyModelsBase.@assert_or_log
— Macroassert_or_log(ex, msg)
Macro that extends the behaviour of the @assert
macro. The switch ASSERTS_AS_LOG
, controls if the macro should act as a logger or a normal @assert
. This macro is designed to be used to check whether the data provided is consistent.