Internals - EnergyModelsInvestment extension
Index
EMIExt.InvestmentModel
EMIExt.SingleInvData
EMIExt.StorageInvData
EnergyModelsInvestments.BinaryInvestment
EnergyModelsInvestments.ContinuousInvestment
EnergyModelsInvestments.DiscreteInvestment
EnergyModelsInvestments.FixedInvestment
EnergyModelsInvestments.PeriodLife
EnergyModelsInvestments.RollingLife
EnergyModelsInvestments.SemiContinuousInvestment
EnergyModelsInvestments.SemiContinuousOffsetInvestment
EnergyModelsInvestments.StudyLife
EMIExt.check_inv_data
EMIExt.objective_invest
EnergyModelsBase.check_node_data
EnergyModelsBase.constraints_capacity_installed
EnergyModelsBase.objective
EnergyModelsBase.variables_capex
EnergyModelsInvestments.has_investment
EnergyModelsInvestments.investment_data
Extension
Types
EMIExt.InvestmentModel
— TypeInvestmentModel <: EMB.InvestmentModel
Internal type for InvestmentModel
. The introduction of an internal type is necessary as extensions do not allow to export functions or types.
EMIExt.SingleInvData
— TypeSingleInvData <: EMB.SingleInvData
Internal type for SingleInvData
. The introduction of an internal type is necessary as extensions do not allow to export functions or types.
EMIExt.StorageInvData
— TypeStorageInvData <: EMB.StorageInvData
Internal type for StorageInvData
. The introduction of an internal type is necessary as extensions do not allow to export functions or types.
Functions
EMIExt.check_inv_data
— Functioncheck_inv_data(
inv_data::AbstractInvData,
capacity_profile::TimeProfile,
𝒯,
message::String,
check_timeprofiles::Bool,
)
Performs various checks on investment data introduced within EnergyModelsInvestments
Checks
- For each field with
TimeProfile
:- If the
TimeProfile
is aStrategicProfile
, it will check that the profile is in accordance with theTimeStructure
TimeProfile
s inInvestmentData
cannot includeOperationalProfile
,RepresentativeProfile
, orScenarioProfile
as this is not allowed through indexing on theTimeProfile
.
- If the
- The field
:min_add
has to be less than:max_add
if the investment mode is given byContinuousInvestment
orSemiContiInvestment
. - Existing capacity cannot be larger than
:max_inst
capacity in the beginning. IfNoStartInvData
is used, it also checks that the theTimeProfile
capacity_profile
is not includingOperationalProfile
,RepresentativeProfile
, orScenarioProfile
to avoid indexing problems.
EMIExt.objective_invest
— Functionobjective_invest(m, elements, 𝒯ᴵⁿᵛ::TS.AbstractStratPers, modeltype::EnergyModel)
Create JuMP expressions indexed over the investment periods 𝒯ᴵⁿᵛ
for different elements. The expressions correspond to the investments into the different elements. They are not discounted and do not take the duration of the investment periods into account.
By default, objective expressions are included for:
elements = 𝒩::Vector{<:Node}
. In the case of a vector of nodes, the function returns the sum of the capital expenditures for all nodes whose method of the functionhas_investment
returns true. In the case ofStorage
nodes, all capacity investments are considiredelements = 𝒩::Vector{<:Link}
. In the case of a vector of links, the function returns the sum of the capital expenditures for all links whose method of the functionhas_investment
returns true.
It is also possible to provide a tuple 𝒳
for only operational or only investment objective contributions. In this situation, the expression returns a value of 0 for all investment periods.
EnergyModelsBase
Methods
EnergyModelsBase.variables_capex
— MethodEMB.variables_capex(m, 𝒩::Vector{<:EMB.Node}, 𝒯, modeltype::AbstractInvestmentModel)
EMB.variables_capex(m, ℒ::Vector{<:Link}, 𝒯, modeltype::AbstractInvestmentModel)
Declaration of different capital expenditures (CAPEX) variables for the element types introduced in EnergyModelsBase
. CAPEX variables are only introduced for elements that have in investments as identified through the function EMI.has_investment
. All investment variables are declared for all investment periods.
EnergyModelsBase
introduces two elements for an energy system, and hence, provides the user with two individual methods for both 𝒩::Vector{<:EMB.Node}
and 𝒩::Vector{<:Link}.
The individual capacities require the same variable although with different names. Hence, **prefix**
should be replaced in the following to
cap
for all nodes with investments except forStorage
andAvailability
nodes,stor_level
for the storage level capacity ofStorage
nodes,stor_charge
for the charge capacity ofStorage
nodes,stor_discharge
for the discharge capacity ofStorage
nodes, andlink_cap
for [Link
]s.
The individual variables are then given by:
**prefix**_capex
are the capital expenditures in noden
in investment periodt_inv
. The CAPEX variable take into account the invested capacity.**prefix**_current
is the capacity of noden
in investment periodt_inv
. It is introduced in addition tocap_inst
to simplify the model design.**prefix**_add
are the additions in the installed capacity of noden
in investment periodt_inv
. Capacity additions are occuring at the beginning of an investment period.**prefix**_rem
are the reduction in the installed capacity of noden
in investment periodt_inv
. Capacity reductions are occuring at the end of an investment period.**prefix**_invest_b
is an auxiliary variable used in some investment modes for the additions in capacities.**prefix**_remove_b
is an auxiliary variable used in some investment modes for the reduction of capacities.
EnergyModelsBase.objective
— MethodEMB.objective(m, 𝒳, 𝒫, 𝒯, modeltype::AbstractInvestmentModel)
Create objective function overloading the default from EMB for AbstractInvestmentModel
.
Maximize Net Present Value from investments (CAPEX) and operations (OPEX and emission costs)
TODO:
Consider adding contributions from
- revenue (as positive variable, adding positive)
- maintenance based on usage (as positive variable, adding negative)
These variables would need to be introduced through the package SparsVariables
.
Both are not necessary, as it is possible to include them through the OPEX values, but it would be beneficial for a better separation and simpler calculations from the results.
EnergyModelsBase.constraints_capacity_installed
— Methodconstraints_capacity_installed(m, n::Node, 𝒯::TimeStructure, modeltype::AbstractInvestmentModel)
constraints_capacity_installed(m, n::Storage, 𝒯::TimeStructure, modeltype::AbstractInvestmentModel)
constraints_capacity_installed(m, l::Link, 𝒯::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 or link type. This is implemented for Storage
nodes where 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.
EnergyModelsBase.check_node_data
— MethodEMB.check_node_data(n::EMB.Node, data::InvestmentData, 𝒯, modeltype::AbstractInvestmentModel, check_timeprofiles::Bool)
EMB.check_node_data(n::Storage, data::InvestmentData, 𝒯, modeltype::AbstractInvestmentModel, check_timeprofiles::Bool)
Performs various checks on investment data for standard and Storage
nodes.
Checks for standard nodes
- Each node can only have a single
InvestmentData
. - All checks incorporated in the function
check_inv_data
.
Checks for Storage
nodes
- Each node can only have a single
InvestmentData
. - The
InvestmentData
must beStorageInvData
. - For each individual investment field all checks incorporated in the function
check_inv_data
.
EnergyModelsInvestments
Constructors
The following constructors are only relevant for the legacy constructors introduced within the extension. They do not provide any additional information.
EnergyModelsInvestments.BinaryInvestment
— TypeWhen the field cap
is not included, it is assumed that its value is FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
EnergyModelsInvestments.ContinuousInvestment
— TypeWhen the fields min_add
and max_add
are not included, it is assumed that their values are FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
EnergyModelsInvestments.DiscreteInvestment
— TypeWhen the field increment
is not included, it is assumed that its value is FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
EnergyModelsInvestments.FixedInvestment
— TypeWhen the field cap
is not included, it is assumed that its value is FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
EnergyModelsInvestments.PeriodLife
— TypeWhen the field lifetime
is not included, it is assumed that its value is FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
EnergyModelsInvestments.RollingLife
— TypeWhen the field lifetime
is not included, it is assumed that its value is FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
EnergyModelsInvestments.SemiContinuousInvestment
— TypeWhen the fields min_add
and max_add
are not included, it is assumed that their values are FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
EnergyModelsInvestments.SemiContinuousOffsetInvestment
— TypeWhen the fields min_add
, max_add
, and capex_offset
are not included, it is assumed that their values are FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
EnergyModelsInvestments.StudyLife
— TypeWhen the field lifetime
is not included, it is assumed that its value is FixedProfile(0)
. This behavior is only for allowing the legacy constructor to work, while it will be removed in the near future.
Methods
EnergyModelsInvestments.has_investment
— FunctionEMI.has_investment(n::EMB.Node)
For a given Node n
, checks that it contains the required investment data.
EMI.has_investment(l::Link)
For a given Link l
, checks that it contains the required investment data.
EMI.has_investment(n::Storage, field::Symbol)
For a given Storage
node, checks that it contains investments for the field field
, that is :charge
, :level
, or :discharge
.
EnergyModelsInvestments.investment_data
— FunctionEMI.investment_data(inv_data::SingleInvData)
Return the investment data of the investment data SingleInvData
.
EMI.investment_data(n::EMB.Node)
EMI.investment_data(l::Link)
EMI.investment_data(n::EMB.Node, field::Symbol)
EMI.investment_data(l::Link, field::Symbol)
Return the InvestmentData
of the Node n
or Link l
. It will return an error if the if the Node n
or Link l
does not have investment data.
If field
is specified, it returns the InvData
for the corresponding capacity.