Internal functions

Index

Variable creation functions

Most of the variable creation functions in EnergyModelsGasNetworks is built on the existing methods in EnergyModelsBase.

EnergyModelsBase.variables_nodeFunction
EMB.variables_node(m, 𝒩ᶜ::Vector{<:Compressor}, 𝒯, modeltype::EMB.EnergyModel)

When the node vector is a Vector{<:Compressor} the potential increase (potential_Δ) variables are created for each compressor and timestep.

source
EnergyModelsBase.variables_flow_resourceFunction
EMB.variables_flow_resource(m, 𝒩::Vector{<:EMB.Node}, 𝒫::Vector{<:ResourcePressure}, 𝒯, modeltype::EMB.EnergyModel)
EMB.variables_flow_resource(m, 𝒩::Vector{<:EMB.Node}, 𝒫::Vector{<:ResourcePooling}, 𝒯, modeltype::EMB.EnergyModel)

Define additional potential and blending variables for nodes depending on the resources in the system. If exists 𝒫::Vector{<:ResourcePressure} then we create potential variables If exists 𝒫::Vector{<:ResourcePooling{Any}} then we create blending proportion variables

source
EMB.variables_flow_resource(m, ℒ::Vector{<:EMB.Link}, 𝒫::Vector{:ResourcePressure}, 𝒯, modeltype::EnergyModel)

Define additional pressure-related variables for links if there are ResourcePressure in the system. Note! There is no blending variables associated to links.

source

Constraint functions

The functions used to dispatch on the type of Resource and element (i.e., Link and Node) are defined by extending the EnergyModelsBase package.

EnergyModelsBase.constraints_resourceFunction
EMB.constraints_resource(m, n::EMB.Node, 𝒯, 𝒫::Vector{:ResourcePressure}, modeltype::EMB.EnergyModel)
EMB.constraints_resource(m, n::EMB.Node, 𝒯, 𝒫::Vector{:ResourcePooling{Any}}, modeltype::EMB.EnergyModel)  
EMB.constraints_resource(m, n::EMB.Node, 𝒯, 𝒫::Vector{:ResourcePooling{ResourcePressure}}, modeltype::EMB.EnergyModel)

Add blending and/or pressure related constraints to node n based on specific resource types.

  • If 𝒫::Vector{<:ResourcePressure} then it adds only pressure related constraints
  • If 𝒫::Vector{<:ResourcePooling{Any}} then it adds only blending related constraints
  • If 𝒫::Vector{<:ResourcePooling{ResourcePressure}} then it adds both pressure and blending related constraints

Note! The blending constraints for nodes require ℒ:Vector{<:EMB.Link} to be passed as argument. Thus, all of them are defined in constraints_couple_resource() functions.

source
EMB.constraints_resource(m, l::EMB.Link, 𝒯, 𝒫::Vector{<:ResourcePressure}, modeltype::EMB.EnergyModel)
EMB.constraints_resource(m, l::EMB.Link, 𝒯, 𝒫::Vector{<:ResourcePooling{Any}}, modeltype::EMB.EnergyModel)  
EMB.constraints_resource(m, l::EMB.Link, 𝒯, 𝒫::Vector{<:ResourcePooling{ResourcePressure}}, modeltype::EMB.EnergyModel)

Add blending and/or pressure related constraints to node l based on specific resource types transported through l`.

  • If 𝒫::Vector{<:ResourcePressure} then it adds only pressure related constraints
  • If 𝒫::Vector{<:ResourcePooling{Any}} then it adds only blending related constraints
  • If 𝒫::Vector{<:ResourcePooling{ResourcePressure}} then it adds both pressure and blending related constraints

Note! The blending constraints for nodes require ℒ:Vector{<:EMB.Link} to be passed as argument. Thus, all of them are defined in constraints_couple_resource() functions.

source
EnergyModelsBase.constraints_couple_resourceFunction
EMB.constraints_couple_resource(m, 𝒩::Vector{<:EMB.Node}, ℒ::Vector{<:EMB.Link}, 𝒫::Vector{<:ResourcePressure}, 𝒯, modeltype::EMB.EnergyModel)
EMB.constraints_couple_resource(m, 𝒩::Vector{<:EMB.Node}, ℒ::Vector{<:EMB.Link}, 𝒫::Vector{<:ResourcePooling{Any}}, 𝒯, modeltype::EMB.EnergyModel)
EMB.constraints_couple_resource(m, 𝒩::Vector{<:EMB.Node}, ℒ::Vector{<:EMB.Link}, 𝒫::Vector{<:ResourcePooling{ResourcePressure}}, 𝒯, modeltype::EMB.EnergyModel)

Add blending and/or pressure related coupling constraints between nodes and links based on specific resource types.

source
EnergyModelsBase.create_linkFunction
EMB.create_link(m, l::CapDirect, 𝒯, 𝒫::Vector{<:CompoundResource}, modeltype::EMB.EnergyModel)

Dispatched function for setting the constraints for a link of type CapDirect.

source
EnergyModelsBase.constraints_capacityFunction
EMB.constraints_capacity(m, l::CapDirect, 𝒯, modeltype::EMB.EnergyModel)

Function for creating the constraints on the maximum capacity of a link CapDirect.

source
EMB.constraints_capacity(m, n::UnitConversion, 𝒯, modeltype::EMB.EnergyModel)

Remove the capacity constraints for UnitConversion nodes. These nodes do not have :cap_use.

source
EnergyModelsBase.constraints_flow_inFunction
EMB.constraints_flow_in(m, n::PoolingNode, 𝒯::TimeStructure, modeltype::EMB.EnergyModel)

Function for creating the constraint on the inlet flow of a PoolingNode. The sum of the flows from all input links must be equal to the used capacity of the node. It differs from generic nodes in that it is not defined as a proportion of the :input and :output fields.

source
EMB.constraints_flow_in(m, n::UnitConversion, 𝒯::TimeStructure, modeltype::EMB.EnergyModel)

Remove the flowin constraints for UnitConversion nodes. These nodes do not use :capuse, instead flows are calculated based on their data extension in EMB.constraintsextdata.

source
EnergyModelsBase.constraints_flow_outFunction
EMB.constraints_flow_out(m, n::UnitConversion, 𝒯::TimeStructure, modeltype::EMB.EnergyModel)

Remove the flowout constraints for UnitConversion nodes. These nodes do not use :capuse, instead flows are calculated based on their data extension in EMB.constraintsextdata.

source

Then, specific functions in EnergyModelsGasNetworks are defined for the generation of the flow-pressure and pooling constraints.

Those for flow-pressure relationships are:

EnergyModelsGasNetworks.constraints_balance_pressureFunction
constraints_balance_pressure(m, n::EMB.Node, 𝒯, 𝒫::Vector)
constraints_balance_pressure(m, n::EMB.NetworkNode, 𝒯, 𝒫::Vector{<:CompoundResource})
constraints_balance_pressure(m, n::SimpleCompressor, 𝒯, 𝒫::Vector{<:CompoundResource})
constraints_balance_pressure(m, n::PoolingNode, 𝒯, 𝒫::Vector{<:ResourcePressure})
constraints_balance_pressure(m, n::PoolingNode, 𝒯, 𝒫::Vector{<:ResourcePooling{ResourcePressure}})
constraints_balance_pressure(m, l::EMB.Link, 𝒯, 𝒫::Vector{<:CompoundResource})

Set internal balance pressures between potential_in and potential_out in Nodes n and Links l`. The balance will depend on type of nodes:

  • For NetworkNode nodes, the inlet and outlet potentials are equal.
  • For SimpleCompressor nodes, the inlet potential is lower than or equal to the outlet potential.
  • For PoolingNode nodes, the inlet potential of all input resources is equal to the outlet potential of all output resources.
  • For Links, the inlet potential is higher than or equal to the outlet potential. if there is no flow through l, both potentials are set to zero.

Note: Sinks and Source nodes do not have internal pressure balances, as their potentials are only defined at inlet or outlet respectively.

source
EnergyModelsGasNetworks.constraints_pressure_boundsFunction
constraints_pressure_bounds(m, n::Node, data::T, 𝒯, 𝒫::Vector{<:CompoundResource}) where {T<:PressureData}
constraints_pressure_bounds(m, n::Sink, data::T, 𝒯, 𝒫::Vector{<:CompoundResource}) where {T<:PressureData}
constraints_pressure_bounds(m, l::Link, data::T, 𝒯, 𝒫::Vector{<:CompoundResource}) where {T<:PressureData}

Set the pressure limits according to the PressureData data assigned to Node n and Link l. If n is a Sink, the limits are applied to the inlet potential. Otherwise, the limits are applied to the outlet potential. For Links, the limits are applied to the outlet potential only if the link has flow.

The data can be of type:

  • MaxPressureData, which will set a maximum pressure bound.
  • MinPressureData, which will set a minimum pressure bound.
  • FixPressureData, which will set an equality pressure bound.
source
EnergyModelsGasNetworks.constraints_pressure_coupleFunction
constraints_pressure_couple(m, n::EMB.Source, ℒ, 𝒯, 𝒫::Vector{<:CompoundResource})
constraints_pressure_couple(m, n::EMB.Availability, ℒ, 𝒯, 𝒫::Vector{<:CompoundResource})
constraints_pressure_couple(m, n::SimpleCompressor, ℒ, 𝒯, 𝒫::Vector{<:CompoundResource})
constraints_pressure_couple(m, n::PoolingNode, ℒ, 𝒯, 𝒫::Vector{<:CompoundResource})
constraints_pressure_couple(m, n::EMB.Sink, ℒ, 𝒯, 𝒫::Vector{<:CompoundResource})

Constraints setting the pressure balance between nodes and links.

Availability nodes do not allow increase in potential, while SimpleCompressor nodes allow it.

source
EnergyModelsGasNetworks.constraints_flow_pressureFunction
constraints_flow_pressure(m, l::EMB.Link, 𝒯, 𝒫::Vector{<:ResourcePressure})
constraints_flow_pressure(m, l::EMB.Link, 𝒯, 𝒫::Vector{<:ResourcePooling{<:ResourcePressure}})
constraints_flow_pressure(m, l::EMB.Link, 𝒯, 𝒫::Vector{<:Resource})  
constraints_flow_pressure(m, l::EMB.Direct, 𝒯, 𝒫::Vector)

Setting Weymouth constraints in link l. This calculates the flow through l based on the pressure difference between inlet and outlet. The Weymouth equation will be approximated using the first-order Taylor expansion when the Resource is a ResourcePressure. For ResourceComponentPotential, a Piecewise Affine Approximation (PWA) will be used.`

source
EnergyModelsGasNetworks.constraints_energy_potentialFunction
constraints_energy_potential(m, n::SimpleCompressor, 𝒯, 𝒫, modeltype::EMB.EnergyModel)
constraints_energy_potential(m, n::EMB.Node, 𝒯, 𝒫, modeltype::EMB.EnergyModel)

Sets the relationship between energy needs and pressure increase, or any other parameter in Compressor n that determines its energy consumption. Skip if the node is not a type Compressor.

If n is a SimpleCompressor, the energy consumption will be calculated as the product of the flow through the compressor, and the energy input required per unit of flow. This is defined with the default constraint constraints_flow_in().

Note! If new Compressor types are created with different relationships between energy flow and pressure increase, this function should be updated to include the new type and relationship.

source
EnergyModelsGasNetworks.constraints_bidirectional_pressureFunction

" constraintsbidirectionalpressure(m, l::EMB.Link, ℒ, 𝒯, 𝒫) constraintsbidirectionalpressure(m, l::EMB.Direct, ℒ, 𝒯, 𝒫)

Ensure that parallel links defining bidirectionality cannot have flow at the same time. The link without flow will automatically have zero linkinpotential and linkoutpotential due to the constraints_balance_pressure constraints.

source

For pooling constraints:

EnergyModelsGasNetworks.constraints_proportionFunction
constraints_proportion(m, n::EMB.Source, ℒ::Vector{<:EMB.Link}, 𝒯, 𝒫::Vector{ResourcePooling})
constraints_proportion(m, n::EMB.Node, ℒ::Vector{<:EMB.Link}, 𝒯, 𝒫::Vector{ResourcePooling})

Keeps track of the proportions of flows from sources at each node n. Source nodes have their proportions fixed to 1 for their own resource and 0 for others.

source
EnergyModelsGasNetworks.constraints_qualityFunction
constraints_quality(m, n::EMB.Source, ℒ::Vector{<:EMB.Link}, 𝒯, 𝒫::Vector{<:ResourcePooling})
constraints_quality(m, n::EMB.Node, ℒ::Vector{<:EMB.Link}, 𝒯, 𝒫::Vector{<:ResourcePooling})

Defines the maximum and minimum quality constraints for a node n based on the blending data. Sourcenodes do not have quality constraints.

source
EnergyModelsGasNetworks.constraints_proportion_sourceFunction
function constraints_proportion_source(m, 𝒩::Vector{<:EMB.Node}, ℒ::Vector{<:EMB.Link}, 𝒯, 𝒫::Vector{<:ResourcePooling})

Set standard proportion_source values for all nodes. For nodes of type Source, the proportion source from itself is set to 1 and from other sources to 0. For other nodes, the proportion source from non-associated sources is set to 0. Non-associated sources are those that are not upstream of the node.

source
EnergyModelsGasNetworks.constraints_trackingFunction
constraints_tracking(m, n::EMB.Source, ℒ::Vector{<:EMB.Link}, 𝒯, 𝒫::Vector{<:ResourcePooling})
constraints_tracking(m, n::EMB.Node, ℒ::Vector{<:EMB.Link}, 𝒯, 𝒫::Vector{<:ResourcePooling})

Tracking the proportion of subresources at node n. Required for linking with the pressure constraints. If n is a Source, the :proportiontrack variables are fixed to 1 for its own resources and 0 for others. For other node types, the :proportiontrack variables are defined based on the :proportion_source variables of upstream sources.

source

For unit conversion:

EnergyModelsBase.constraints_ext_dataFunction
EMB.constraints_ext_data(m, n::Node, 𝒯, 𝒫, modeltype::EnergyModel, data::FlowToEnergyData)

Function to convert flow rates to energy rates (e.g., Sm3/d to MWh/d). The time basis of the flow rates is preserved in the conversion.

source

Utils

General utils are:

EnergyModelsGasNetworks.nodes_upstream_ofFunction
nodes_upstream_of(n::Node, ℒ::Vector{<:Link})

Tracks all nodes associated with a given node n through the links in . We refer to associated to all the nodes that lead to n following the direction of the links.

source
EnergyModelsGasNetworks.sources_upstream_ofFunction
sources_upstream_of(n::Node, ℒ::Vector{<:Link})
sources_upstream_of(n::EMB.Node, ℒ::Vector{<:EMB.Link}, resources::Vector{EMB.Resources})

Tracks all nodes associated to n and filter by source nodes. If resources is provided, only sources which output any of the resources in sub_res are returned.

source
EnergyModelsBase.link_dataFunction
link_data(l::CapDirect)

Returns the [ExtensionData] array of link l.

It overwrites the EMB.link_data(l::Link) method, which returns an empty ExtensionData vector.

source

Specific utils to perform calculations on input data:

EnergyModelsGasNetworks.calculate_flow_to_approximateFunction
calculate_flow_to_approximate(constant, x1, x2, x3)

Calculates the flow of gas with the Weymouth equation using the normalised weymouth constant.

Typically, the constant in the Weymouth equation depends on the specific gravity of the gas. Here, we need instead a normalised it with respect to the specific gravity. This allows to calculate the flows considering the different proportions of the components.

Variables

  • weymouth_ct::Float64 -> Normalised Weymouth constant
  • x1::Float64 -> Inlet pressures
  • x2::Float64 -> Outlet pressures
  • x3::Float64 -> Proportion of tracking component
  • molmass_other::Float64 -> Molar mass of the other component in the blend (e.g., for methane is 16.042 g/mol)
  • molmass_track::Float64 -> Molar mass of the tracking component (e.g., for hydrogen is 2.016 g/mol)
source
EnergyModelsGasNetworks.get_pwaFunction
function get_pwa(data_pressure::PressureLinkData, data_blend::BlendData, optimizer; resolution_prop=0.01)
function get_pwa(l::EMB.Link, optimizer; resolution_prop=0.01)

Generates/retrieves the PWA functions for a link with blending and pressure data to calculate the Weymouth equation with blending.

source
EnergyModelsGasNetworks.get_specific_energy_contentFunction
get_LHV(data::FlowToEnergyData)
get_LHV(data::FlowToEnergyData, p::EMB.Resource)

Collects the resources if Dict{<:Resource,<:Real} (used for ResourcePooling) or the LHV if is a Real (for other types of resources) If the resource p is specified, retrieves the LHV for that specific resource from the dictionary.

source
EnergyModelsGasNetworks.resource_lhvFunction
resource_lhv(n::Node, 𝒫ˡʰᵛ::Vector{ResourcePooling}, data::FlowToEnergyData)
resource_lhv(n::EMB.Node, 𝒫ˡʰᵛ::Vector{Resource}, data::FlowToEnergyData)

Function to calculate the LHV of the input resource for a given node with FlowToEnergyData. If the input resource is of type ResourcePooling, the LHV is calculated as the weighted average of the LHV of the individual resources in the blend. If the input resource is any other type of Resource, the LHV is simply retrieved from the data.

source

Scratch

EnergyModelsGasNetworks integrates the package Scratch.jl, which enables storing mutable containers of data. Specifically, it is applied to managing temporary storage of the piecewise-affine approximation data. In this way, the optimization used for finding the corresponding planes does not need to be performed again if the same conditions (i.e., Weymouth constants, maximum inlet pressure, minimum outlet pressure, pressure steps) are inputs for a link.

All the functions are internally used by EnergyModelsGasNetworks, except delete_cache which can be called directly by the user if necessary.