Optimization variables

EnergyModelsBase creates a variety of default variables for the individual nodes and edges. These default variables are in general also created when new Nodes or Links are developed. It is not necessary to utilize all of the default variables in the individual nodes. It is, however, recommended to include constraints or fixes in this situation using either the @constraint macro or, alternatively, the JuMP function fix(x, value). The latter is the recommended approach.

The majority of the variables in EnergyModelsBase are rate variables. This implies that they are calculated for either an operational period duration of 1, when indexed over operational period $t$, or a strategic period duration of 1, when indexed over strategic period $t_\texttt{inv}$. Typical units for rates are MW for energy streams, tonne/hour for mass streams, tonne/year for strategic emissions, and €/year for operating expenses. In this example, the duration of an operational period of 1 corresponds to an hour, while the duration of a strategic period of 1 corresponds to a year.

Variables that are energy/mass based have that property highlighted in the documentation below. In the standard implementation of EnergyModelsBase, this is only the case for the level of a Storage node, the change of level of the node, and its installed capacity.

Rate variables can also be translated to mass/energy variables. As an example, the total quantity of resource $p$ that flows into node $n$ during operational period $t$ can be calculated by

m[:flow_in][n, t, p] * duration(t)

The multiplication then leads to an energy/mass quantity instead of an energy/mass flow.

The coupling of strategic and operational periods can be achieved through the function scale_op_sp(t_inv, t). This function allows for considering the scaling of the operational periods within a strategic period.

Variable scaling

Variables are in general not scaled. The reason for this approach is to simplify the comparison of individual values independently of the chosen time structure. The following rules apply:

  • Variables do not consider the branch probability when utilizing the TwoLevelTree time structure. This is, e.g., the case for the strategic emission variables or the variable operating expenses that apply per scenario/branch. The branch probability is, however, included when calculating the objective function.
  • Operational variables do not consider the number of repetitions introduced through the parameter op_per_strat as described within the section on strategic periods. This also holds when using RepresentativePeriods.
  • Operational variables do not consider the probability of an operational scenario when using OperationalScenarios.

However, representative variables (indexed over a representative period) include the number of repetitions of the representative period. This may be changed in the next breaking release to be consistent with all other variables.

Operational cost variables

Operational cost variables are included to account for operating expenses (OPEX) of the model. These costs are purely dependent on either the use or the installed capacity of a node $n$. All nodes $n$ (except Availability-nodes) have the following variables representing the operational costs of the nodes:

  • $\texttt{opex\_var}[n, t_\texttt{inv}]$: Variable OPEX of node $n$ in strategic period $t_\texttt{inv}$.
  • $\texttt{opex\_fixed}[n, t_\texttt{inv}]$: Fixed OPEX of node $n$ in strategic period $t_\texttt{inv}$.

The variable OPEX is a cost that derives from using a technology. It is calculated using the function constraints_opex_var. In general, it represents unmodelled feed to a process and the associated costs. Examples are catalyst replacement, cooling water or process water. The variable OPEX can also be utilized to provide values for a profit through using a technology.

The fixed OPEX is a cost that is independent of the usage of a technology. Instead, it is only dependent on the installed capacity. It is calculated using the function constraints_opex_fixed. It represents fixed costs such as labour costs, maintenance, insurance, and taxes.

We also introduce the potential for links with operational costs. By default, links do not introduce new variables. Operational cost variables are only created for a link $l$ if the function has_opex(n::Link) returns true. The following link variables are then declared representing the operational costs of the links:

  • $\texttt{link\_opex\_var}[l, t_\texttt{inv}]$: Variable OPEX of link $l$ in strategic period $t_\texttt{inv}$.
  • $\texttt{link\_opex\_fixed}[l, t_\texttt{inv}]$: Fixed OPEX of link $l$ in strategic period $t_\texttt{inv}$.

Capacity variables

Capacity variables focus on both the capacity usage and installed capacity. The capacity variables are also created for all nodes except for Availability nodes. Capacity variables are differentiated between Storage nodes and all other Nodes. The implementation of the capacity variables allows for a time-varying capacity during an operational period for inclusion of variations in the demand in Sink nodes. It is, however, not possible to invest in a time-varying capacity.

The following capacity variables are created for node types other than Storage:

  • $\texttt{cap\_use}[n, t]$: Absolute capacity usage of node $n$ at operational period $t$, and
  • $\texttt{cap\_inst}[n, t]$: Installed capacity of node $n$ at operational period $t$.

The capacity usage $\texttt{cap\_use}$ is the utilization of the installed capacity. It is declared in absolute values to avoid bilinearities when investing in capacities. It is normally constrained by the variable $\texttt{cap\_inst}$ of the individual nodes, except for Sink nodes.

The capacity variables for Storage nodes differentiate between storage capacity (stored energy in the Storage node) and rate of storage (storage rate of a Storage node). The latter is furthermore differentiated between charging and discharging a Storage node. A key reason for this approach is that it is in general possible to invest both in the storage rate (e.g., the AC-DC transformer required in battery storage) as well as in the storage capacity (e.g., the number of cells in battery storage). The same also holds for pumped hydro storage and storage of gases, where there is a further differentiation between the maximum charging and discharging rates. The differentiation leads to the following variables for Storage nodes:

  • $\texttt{stor\_level}[n, t]$: Absolute level of energy/mass stored in a Storage node $n$ at operational period $t$ with a typical unit of GWh or t,
  • $\texttt{stor\_level\_inst}[n, t]$: Installed storage capacity in a Storage node $n$ at operational period $t$ , that is the upper bound for the variable $\texttt{stor\_level}[n, t]$, with a typical unit of GWh or t,
  • $\texttt{stor\_charge\_use}[n, t]$: Usage of the charging rate of a Storage node $n$ at operational period $t$ with a typical unit of GW or t/h,
  • $\texttt{stor\_charge\_inst}[n, t]$: Maximum available charging rate of a Storage node $n$ at operational period $t$, that is the upper bound for the variable $\texttt{stor\_charge\_use}[n, t]$, with a typical unit of GW or t/h.
  • $\texttt{stor\_discharge\_use}[n, t]$: Usage of the discharging rate of a Storage node $n$ at operational period $t$ with a typical unit of GW or t/h, and
  • $\texttt{stor\_discharge\_inst}[n, t]$: Maximum available discharging rate of a Storage node $n$ at operational period $t$, that is the upper bound for the variable $\texttt{stor\_discharge\_use}[n, t]$, with a typical unit of GW or t/h.
Note

It is not necessary that a Storage node has a charge and discharge capacity. It is possible to not specify a capacity for charging and discharging. In this instance, the variables for the installed capacities are omitted, and the charging and discharging usage is unlimited.

The storage level is always defined for the end of the operational period it is indexed over. In addition, there are three variables for the storage level that behave slightly differently:

  • $\texttt{stor\_level\_Δ\_op}[n, t]$: Change of the absolute level of energy/mass stored in a Storage node $n$ in operational period $t$ with a typical unit of GWh or t, and
  • $\texttt{stor\_level\_Δ\_rp}[n, t_{rp}]$: Change of the absolute level of energy/mass stored in a Storage node $n$ in representative period $t_{rp}$ with a typical unit of GWh or t, and
  • $\texttt{stor\_level\_Δ\_sp}[n, t_\texttt{inv}]$: Change of the absolute level of energy/mass stored in a Storage node $n$ in strategic period $t_\texttt{inv}$ with a typical unit of GWh or t.

These variables are introduced to track the change in the storage level during an operational period, a representative period, or an investment period, respectively. They can be considered as helper variables to account for the duration of the operational period as well as the total change within a representative period. $\texttt{stor\_level\_Δ\_rp}$ is only declared if the TimeStructure includes RepresentativePeriods while $\texttt{stor\_level\_Δ\_sp}$ is introduced as an empty SparseVariables container. The application of RepresentativePeriods is explained in How to use TimeStruct.jl. The utilization of $\texttt{stor\_level\_Δ\_sp}$ requires including the following loop in the function variables_node for the given Storage array 𝒩ˢᵘᵇ::Vector{<:NewStorageNode}:

for t_inv ∈ 𝒯ᴵⁿᵛ, n ∈ 𝒩ˢᵘᵇ
    insertvar!(m[:stor_level_Δ_sp], n, t_inv)
end

We also introduce the potential for links with capacities. By default, links do not introduce new variables. The capacity variable is only created for a link $l$ if the function has_capacity(n::Link) returns true. The following link variable is then declared to represent the capacity of links:

  • $\texttt{link\_cap\_inst}[l, t]$: Installed capacity of link $l$ at operational period $t$.
Inclusions of investments

The variables $\texttt{cap\_inst}$, $\texttt{stor\_charge\_inst}$, $\texttt{stor\_level\_inst}$, $\texttt{stor\_discharge\_inst}$, and $\texttt{link\_cap\_inst}$ are used in EnergyModelsInvestment to allow for investments in the capacity of individual nodes.

Flow variables

Flow variables correspond to the input to and output from both technology nodes and links. They are always positive to avoid backflow.

The following flow variables are defined for the nodes:

  • $\texttt{flow\_in}[n, t, p]$ represents the flow rate of resource $p$ into node $n$ at operational period $t$. It is created for subtypes of NetworkNode and Sink based on the field input of the composite type.
  • $\texttt{flow\_out}[n, t, p]$ represents the flow rate of resource $p$ out of node $n$ at operational period $t$. It is created for subtypes of Source and NetworkNode based on the field output of the composite type.

Links also have corresponding flow variables given by:

  • $\texttt{link\_in}[l, t, p]$ represents the flow rate of resource $p$ into link $l$ at operational period $t$, and
  • $\texttt{link\_out}[l, t, p]$ represents the flow rate of resource $p$ out of link $l$ at operational period $t$.

The resource index $p$ is created based on the intersection of the output of the input node $n_{in}$ and the input of the output node $n_{out}$ through the function EMB.link_res(l::Link). Mathematically, this is given by

$\mathcal{P}^{link} = \mathcal{P}^{n^{out}_{in}} \cap \mathcal{P}^{n^{in}_{out}}.$

It is also possible to create a new method for this function to limit the resources a link can transport.

Emission variables

Emission variables are used to account for emissions of the individual technologies. Resources that can be emitted are defined through the type ResourceEmit. Nodes do not necessarily have associated emission variables. Emission variables are only created for a node $n$ if the function has_emissions(n::EMB.Node) returns true. This is the case for all nodes that have EmissionsData within their field data, as well as for a RefStorage node if a ResourceEmit is stored. The following node variable is then declared for all emission resource 𝒫ᵉᵐ:

  • $\texttt{emissions\_node}[n, t, p_\texttt{em}]$: Emissions of node $n$ at operational period $t$ of emission resource $p_\texttt{em}$.

Similarly, it is not necessary that links have associated emission variables. Emission variables are only created for a link $l$ if the function has_emissions(n::Link) returns true. The following link variable is then declared for all emission resource 𝒫ᵉᵐ:

  • $\texttt{emissions\_link}[n, t, p_\texttt{em}]$: Emissions of link $l$ at operational period $t$ of emission resource $p_\texttt{em}$.

In addition, EnergyModelsBase declares the following variables for the global emissions:

  • $\texttt{emissions\_total}[t, p_\texttt{em}]$: Total emissions of ResourceEmit $p_\texttt{em}$ in operational period $t$, and
  • $\texttt{emissions\_strategic}[t_\texttt{inv}, p_\texttt{em}]$: Total emissions of ResourceEmit $p_\texttt{em}$ in strategic period $t_\texttt{inv}$.

These emission variables introduce limits on the total emissions of a resource through the field emission_limit of an EnergyModel in the function EMB.variables_emission.

Sink variables

Sink nodes are somewhat different from the other nodes because they have additional variables associated with them. A key point here is to keep the overall mass balance intact while allowing for both overfulfilling and not meeting the demand. These variables are:

  • $\texttt{sink\_surplus}[n, t]$: Surplus of energy/mass to Sink $n$ at operational period $t$, and
  • $\texttt{sink\_deficit}[n, t]$: Deficit of energy/mass to Sink $n$ at operational period $t$.

The surplus in a sink corresponds to the energy/mass that is supplied to the sink in addition to the demand. The deficit in a sink corresponds to the energy/mass that is not supplied to the sink although the demand is specified. Both variables correspond to slack variables of the optimization problem. They simplify the problem and can make certain types of formulations feasible. It is possible to provide penalties for both surplus and deficit. This is implemented through the field penalty in the RefSource node.

Node types and respective variables

As outlined in the introduction, EnergyModelsBase declares different variables for each Node. These variables are for the individual nodes given in the subsections below.

Source

NetworkNode, except for Storage

Storage

Sink