CapacityCostLink
CapacityCostLink links model the transport of energy between two nodes with capacity-dependent operational costs applied to a specified resource. Unlike standard Direct links, they enable cost modeling based on maximum capacity utilization over defined time periods. This is useful for applications such as transmission networks, pipelines, or interconnectors where usage fees scale with peak capacity demands.
In addition, they only allow the transport of a single, specified Resource.
Some of the fields of this link cannot be represented in EnergyModelsGUI. The reason for that limitation is that EnergyModelsGUI does not yet support partitions of TimePeriods. EnergyModelsGUI can still be utilized for all other fields.
The meaning of the field cap_period_duration was changed when moving from 0.3 to 0.4:
When specifying a number, the previous meaning of the number of operational periods was changed to the sum of the durations of the operational periods. The reason for this change is to make the link behavior less dependent on the operational resolution. The following change is hence required if you have operational durations differing from 1:
# time structure ts = SimpleTimes(10, 2) # old behavior, corresponding to 2 periods cap_period_duration = 2 # new behavior, corresponding to periods whocse duration sums to at least 4 cap_period_duration = 4When specifying a vector, the previous scaling based on the chosen value of
op_per_stratwas removed as it is in our opinion more straightforward to base it on the actual operational time structure. The following change is hence required:# time structure ts = Twolevel(2, 1, SimpleTimes(10, 2); op_per_strat=8760.0) # old behavior, corresponding to 5 periods a 1752 duration based on `op_per_strat` cap_period_duration = [1752, 1752, 1752, 1752, 1752] # new behavior, corresponding to 5 periods a 4 duration based on `SimpleTimes` cap_period_duration = [4, 4, 4, 4, 4]
Introduced type and its fields
CapacityCostLink is implemented as equivalent to an abstract type Link. Hence, it utilizes the same functions declared in EnergyModelsBase.
Standard fields
CapacityCostLink has the following standard fields, equivalent to a Direct link:
id:
The fieldidis only used for providing a name to the link.from::Node:
The node from which there is flow into the link.to::Node:
The node to which there is flow out of the link.formulation::Formulation:
The used formulation of links. If not specified, aLinearlink is assumed.
Additional fields
The following additional fields are included for CapacityCostLink links:
cap::TimeProfile:
The maximum transport capacity of the link for thecap_resource. If the link should contain investments through the application ofEnergyModelsInvestments, it is important to note that you can only useFixedProfileorStrategicProfilefor the capacity, but notRepresentativeProfileorOperationalProfile. In addition, all values have to be non-negative.cap_price::TimeProfile:
The price per unit of maximum capacity usage over the sub-periods. This value is averaged over sub-periods as defined bycap_price_periods. All values have to be non-negative.Price values The value given in
cap_priceis interpreted on the strategic-period scale (e.g., if a strategic-period duration of1corresponds to 1 year, then the natural unit is €/GW/year). Capacity costs are calculated per sub-period and then summed over the strategic period. This means a constant value (e.g., €/GW/year) is effectively applied once for each sub-period (based on the peak within that sub-period), and is not automatically scaled by sub-period duration.Example:
# Modelling a full year with hourly resolution ts = TwoLevel(1, 1, SimpleTimes(8760, 1); op_per_strat=8760.0) # 12 price periods corresponding to months cap_price_periods = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] .* 24 cap_price = 100 # €/GW/yearIf the peak usage is 1 GW in each month, the model computes a total cost of 12 × 100 = 1200 €/year.
To achieve seasonal/monthly peak charges, define multiple
cap_price_periodsand providecap_pricevalues that represent the intended charge per sub-period (or scale the values accordingly).It is planned to change this behavior in the future. The change corresponds to a breaking change as we change the behavior of the model.
cap_period_duration::TimeProfile:
Defines the total duration of a capacity price period.
For instance, if the duration of 1 of the operational time structure is 1 hour andperiod_duration = FixedProfile(24), then each capacity price period spans one day. The capacity price of this node (for a given day, see below) is the given by the maximum capacity usage within a day.
Due to a constructor, it can either be specified as number (the same duration in all capacity price periods), as a vector (varying duration of each capacity price period), or as a time profile (e.g., varying period durations due to varying operational time structures). It cannot be specified asOperationalProfileand must be positive for each individual value.Duration of capacity price periods For investment periods with many operational periods, consider decreasing
cap_period_duration. TheCapacityCostLinkcapacity constraints couple operational periods and can significantly increase solve time. Splitting the horizon into multiple sub-periods reduces this coupling and often makes the problem much easier to solve. In some cases, this also means using more than one capacity price period even if capacity costs occur only annually in reality, depending on model size and complexity.cap_resource::Resource:
TheResourcefor which capacity-dependent costs are applied. ThisResourceis the only transportedResourceby aCapacityCostLink.data::Vector{<:ExtensionData}:
An entry for providing additional data to the model. In the current version, it is used for providing additional investment data whenEnergyModelsInvestmentsis used.
Mathematical description
In the following mathematical equations, we use the name for variables and functions used in the model. Variables are in general represented as
$\texttt{var\_example}[index_1, index_2]$
with square brackets, while functions are represented as
$func\_example(index_1, index_2)$
with parantheses.
Variables
Standard variables
CapacityCostLink utilizes standard variables from the Link type, as described on the page Optimization variables:
Additional variables
Two additional variables track capacity utilization and associated costs over sub-periods:
- $\texttt{ccl\_cap\_use\_max}[l, t_{pd}]$: Maximum capacity usage in sub-period $t_{pd}$ for link $l$.
- $\texttt{ccl\_cap\_use\_cost}[l, t_{pd}]$: Operational cost in sub-period $t_{pd}$ for link $l$.
Constraints
Standard constraints
The applied standard constraint for capacity installed is:
\[\texttt{link\_cap\_inst}[l, t] = capacity(l, t)\]
and the no-loss constraint
\[\texttt{link\_out}[l, t, p] = \texttt{link\_in}[l, t, p] \quad \forall p \in inputs(l)\]
Additional constraints
All additional constraints are created within a new method for the function create_link.
The capacity utilization constraint tracks the maximum usage within each sub-period $t_{sub}$:
\[\texttt{link\_in}[l, t, cap\_resource(l)] \leq \texttt{ccl\_cap\_use\_max}[l, t_{pd}]\]
The capacity cost is calculated as:
\[\texttt{ccl\_cap\_use\_cost}[l, t_{pd}] = \texttt{ccl\_cap\_use\_max}[l, t_{pd}] \times \overline{cap\_price}(l, t_{pd})\]
where $\overline{cap\_price}$ is the average capacity price over the sub-period calculated as:
\[\overline{cap\_price}(l, t_{pd}) = \frac{\sum_{t \in t_{pd}} cap\_price(l, t) \times duration(t)}{\sum_{t \in t_{pd}} duration(t)}\]
Finally, costs are aggregated to each strategic period:
\[\texttt{link\_opex\_var}[l, t_{inv}] = \sum_{t_{pd} \in t_{inv}} \texttt{ccl\_cap\_use\_cost}[l, t_{pd}]\]
In addition, the energy flow of the constrained resource should not exceed the maximum capacity, which is included through the following constraint:
\[\texttt{flow\_in}[l, t, cap\_resource(l)] \leq \texttt{link\_cap\_inst}[l, t]\]