Internals - EnergyModelsInvestment extension

Index

Extension

Types

EMIExt.InvestmentModelType
InvestmentModel <: EMB.InvestmentModel

Internal type for InvestmentModel. The introduction of an internal type is necessary as extensions do not allow to export functions or types.

source
EMIExt.SingleInvDataType
SingleInvData <: EMB.SingleInvData

Internal type for SingleInvData. The introduction of an internal type is necessary as extensions do not allow to export functions or types.

source
EMIExt.StorageInvDataType
StorageInvData <: EMB.StorageInvData

Internal type for StorageInvData. The introduction of an internal type is necessary as extensions do not allow to export functions or types.

source

Functions

EMIExt.check_inv_dataFunction
check_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 a StrategicProfile, it will check that the profile is in accordance with the TimeStructure
    • TimeProfiles in InvestmentData cannot include OperationalProfile, RepresentativeProfile, or ScenarioProfile as this is not allowed through indexing on the TimeProfile.
  • The field :min_add has to be less than :max_add if the investment mode is given by ContinuousInvestment or SemiContiInvestment.
  • Existing capacity cannot be larger than :max_inst capacity in the beginning. If NoStartInvData is used, it also checks that the the TimeProfile capacity_profile is not including OperationalProfile, RepresentativeProfile, or ScenarioProfile to avoid indexing problems.
source
EMIExt.objective_investFunction
objective_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 function has_investment returns true. In the case of Storage nodes, all capacity investments are considired
  • elements = 𝒩::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 function has_investment returns true.
Default function

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.

source

EnergyModelsBase

Methods

EnergyModelsBase.variables_capexMethod
EMB.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}.

Variables and naming conventions

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 for Storage and Availability nodes,
  • stor_level for the storage level capacity of Storage nodes,
  • stor_charge for the charge capacity of Storage nodes,
  • stor_discharge for the discharge capacity of Storage nodes, and
  • link_cap for [Link]s.

The individual variables are then given by:

  • **prefix**_capex are the capital expenditures in node n in investment period t_inv. The CAPEX variable take into account the invested capacity.
  • **prefix**_current is the capacity of node n in investment period t_inv. It is introduced in addition to cap_inst to simplify the model design.
  • **prefix**_add are the additions in the installed capacity of node n in investment period t_inv. Capacity additions are occuring at the beginning of an investment period.
  • **prefix**_rem are the reduction in the installed capacity of node n in investment period t_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.
source
EnergyModelsBase.objectiveMethod
EMB.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.

source
EnergyModelsBase.constraints_capacity_installedMethod
constraints_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.

source
EnergyModelsBase.check_node_dataMethod
EMB.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 be StorageInvData.
  • For each individual investment field all checks incorporated in the function check_inv_data.
source

EnergyModelsInvestments

Constructors

The following constructors are only relevant for the legacy constructors introduced within the extension. They do not provide any additional information.

EnergyModelsInvestments.BinaryInvestmentType

When 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.

source
EnergyModelsInvestments.ContinuousInvestmentType

When 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.

source
EnergyModelsInvestments.DiscreteInvestmentType

When 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.

source
EnergyModelsInvestments.FixedInvestmentType

When 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.

source
EnergyModelsInvestments.PeriodLifeType

When 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.

source
EnergyModelsInvestments.RollingLifeType

When 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.

source
EnergyModelsInvestments.SemiContinuousInvestmentType

When 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.

source
EnergyModelsInvestments.SemiContinuousOffsetInvestmentType

When 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.

source
EnergyModelsInvestments.StudyLifeType

When 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.

source

Methods

EnergyModelsInvestments.has_investmentFunction
EMI.has_investment(n::EMB.Node)

For a given Node n, checks that it contains the required investment data.

source
EMI.has_investment(l::Link)

For a given Link l, checks that it contains the required investment data.

source
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.

source
EnergyModelsInvestments.investment_dataFunction
EMI.investment_data(inv_data::SingleInvData)

Return the investment data of the investment data SingleInvData.

source
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.

source