Utility functions
all_constraints
MacroEnergy.all_constraints
— Functionall_constraints(v::AbstractVertex)
Get all constraints on a vertex.
Arguments
v
: A vertex object that is a subtype of AbstractVertex
Returns
- A vector of all constraint objects on the vertex
Examples
constraints = all_constraints(elec_node)
all_constraints_types
MacroEnergy.all_constraints_types
— Functionall_constraints_types(v::AbstractVertex)
Get the types of all constraints on a vertex.
Arguments
v
: A vertex object that is a subtype of AbstractVertex
Returns
- A vector of types of all constraints on the vertex
Examples
constraint_types = all_constraints_types(elec_node)
asset_ids
MacroEnergy.asset_ids
— Functionasset_ids(system::System; source::String="assets")
Get the set of asset IDs from a system, either from loaded assets or input files.
Arguments
system::System
: The system to get asset IDs fromsource::String
: The source to get asset IDs from. Can be either:"assets"
(default): Get IDs from already loaded assets in the system"inputs"
: Get IDs from input files
Returns
Set{AssetId}
: A set of asset IDs
Examples
# Get IDs from loaded assets
ids = asset_ids(system)
Notes
- If
source="assets"
and no assets are loaded, a warning is issued - If an invalid source is provided, an error is thrown
balance_ids
MacroEnergy.balance_ids
— Functionbalance_ids(v::AbstractVertex)
Get the IDs of all balance equations in a vertex.
Arguments
v
: A vertex object that is a subtype of AbstractVertex
Returns
- A vector of Symbols representing the IDs of all balance equations
Examples
balance_ids = balance_ids(elec_node)
balance_data
MacroEnergy.balance_data
— Functionbalance_data(v::AbstractVertex, i::Symbol)
Get the input data for a specific balance equation in a vertex.
Arguments
v
: A vertex object that is a subtype of AbstractVertexi
: Symbol representing the ID of the balance equation
Returns
- The input data (usually stoichiometric coefficients) for the specified balance equation
Examples
demand_data = balance_data(elec_node, :demand)
create_output_path
MacroEnergy.create_output_path
— Functioncreate_output_path(system::System, path::String=system.data_dirpath)
Create and return the path to the output directory for storing results based on system settings.
Arguments
system::System
: The system object containing settings and configurationpath::String
: Base path for the output directory (defaults to system.data_dirpath)
Returns
String
: Path to the created output directory
The function creates an output directory based on system settings. If OverwriteResults
is false, it will avoid overwriting existing directories by appending incremental numbers (e.g., "001", "002") to the directory name. The directory is created if it doesn't exist.
Example
julia> system.settings
(..., OverwriteResults = true, OutputDir = "result_dir")
julia> output_path = create_output_path(system)
# Returns "path/to/system.data_dirpath/result_dir" or "path/to/system.data_dirpath/result_dir_001" if original exists
julia> output_path = create_output_path(system, "path/to/output")
# Returns "path/to/output/result_dir" or "path/to/output/result_dir_001" if original exists
get_asset_by_id
MacroEnergy.get_asset_by_id
— Functionget_asset_by_id(system::System, id::Symbol)
Find an asset in the system by its ID.
Arguments
system
: A System object containing various assetsid
: Symbol representing the ID of the asset to find
Returns
- The asset object if found
nothing
if no asset with the given ID exists
Examples
# Find a battery asset
battery = get_asset_by_id(system, :battery_SE)
# Find a thermal power plant
thermal_plant = get_asset_by_id(system, :natural_gas_SE)
get_assets_sametype
MacroEnergy.get_assets_sametype
— Functionget_assets_sametype(system::System, asset_type::T) where T<:Type{<:AbstractAsset}
Get all assets of a specific type from the system.
Arguments
system
: A System object containing various assetsasset_type
: The type of assets to retrieve (must be a subtype of AbstractAsset)
Returns
- A vector of assets of the specified type
Examples
# Get all battery assets
batteries = get_assets_sametype(system, Battery)
battery = batteries[1] # first battery in the list
# Get all natural gas thermal power plants
thermal_plants = get_assets_sametype(system, ThermalPower{NaturalGas})
get_asset_types
MacroEnergy.get_asset_types
— Functionget_asset_types(system::System)
Get a vector of the types of all assets in the system.
Arguments
system
: A System object containing various assets
Returns
- A vector of DataTypes representing the type of each asset in the system
Examples
asset_types = get_asset_types(system)
unique(asset_types) # Get unique asset types in the system
get_balance
MacroEnergy.get_balance
— Functionget_balance(v::AbstractVertex, i::Symbol)
Get the mathematical expression of a balance equation in a vertex.
Arguments
v
: A vertex object that is a subtype of AbstractVertexi
: Symbol representing the ID of the balance equation
Returns
- The mathematical expression of the balance equation
Examples
# Get the demand balance expression
demand_expr = get_balance(elec_node, :demand)
get_constraint_by_type
MacroEnergy.get_constraint_by_type
— Functionget_constraint_by_type(v::AbstractVertex, constraint_type::Type{<:AbstractTypeConstraint})
Get a constraint on a vertex by its type.
Arguments
v
: A vertex object that is a subtype of AbstractVertexconstraint_type
: The type of constraint to find
Returns
- If exactly one constraint of the specified type exists: returns that constraint
- If multiple constraints of the specified type exist: returns a vector of those constraints
- If no constraints of the specified type exist: returns
nothing
Examples
balance_constraint = get_constraint_by_type(elec_node, BalanceConstraint)
get_component_by_fieldname
MacroEnergy.get_component_by_fieldname
— Functionget_component_by_fieldname(asset::AbstractAsset, fieldname::Symbol)
Get a component of an asset by its field name (i.e., fieldname of the asset struct
).
Arguments
asset
: An asset object that is a subtype of AbstractAssetfieldname
: Symbol representing the field name of the component to get (i.e., fieldname of the assetstruct
)
Returns
- The component object stored in the specified field
Examples
elec_edge = get_component_by_fieldname(thermal_plant, :elec_edge)
get_component_ids
MacroEnergy.get_component_ids
— Functionget_component_ids(asset::AbstractAsset)
Get the IDs of all components in an asset.
Arguments
asset
: An asset object that is a subtype of AbstractAsset
Returns
- A vector of Symbols representing the IDs of all components in the asset
Examples
component_ids = get_component_ids(thermal_plant)
get_component_by_id
MacroEnergy.get_component_by_id
— Functionget_component_by_id(asset::AbstractAsset, component_id::Symbol)
Find a component (e.g., edges, storages, transformations) of an asset by its ID.
Arguments
asset
: An asset object that is a subtype of AbstractAssetcomponent_id
: Symbol representing the ID of the component to find
Returns
- The component object if found
nothing
if no component with the given ID exists
Examples
elec_edge = get_component_by_id(thermal_plant, :SE_natural_gas_elec_edge)
get_edges
MacroEnergy.get_edges
— Functionget_edges(asset::AbstractAsset; return_ids_map::Bool=false)
get_edges(assets::Vector{<:AbstractAsset}; return_ids_map::Bool=false)
Get all edges from an asset or a vector of assets. If return_ids_map=true
, a Dict
is also returned mapping edge ids to the corresponding asset objects.
Arguments
asset
orassets
: An asset object or vector of assets that are subtypes of AbstractAssetreturn_ids_map
: If true, also return a Dict mapping edge IDs to their corresponding assets (default: false)
Returns
- If
return_ids_map=false
: A vector of edges - If
return_ids_map=true
: A tuple of (vector of edges, Dict mapping edge IDs to assets)
Examples
# Get all edges from a single asset
edges = get_edges(thermal_plant)
get_output_layout
MacroEnergy.get_output_layout
— Functionget_output_layout(system::System, variable::Union{Nothing,Symbol}=nothing)::String
Get the output layout ("wide" or "long") for a specific variable from system settings.
Arguments
system::System
: System containing output layout settingsvariable::Union{Nothing,Symbol}=nothing
: Variable to get layout for (e.g., :Cost, :Flow)
Returns
String indicating layout format: "wide" or "long"
Settings Format
The OutputLayout
setting can be specified in three ways:
Global string setting:
settings = (OutputLayout="wide",) # Same layout for all variables
Per-variable settings using NamedTuple:
settings = (OutputLayout=(Cost="wide", Flow="long"),)
Default behavior:
- Returns "long" if setting is missing or invalid
- Logs warning for unsupported types or missing variables
Examples
# Global layout
system = System(settings=(OutputLayout="wide",))
get_output_layout(system, :Cost) # Returns "wide"
# Per-variable layout
system = System(settings=(OutputLayout=(Cost="wide", Flow="long"),))
get_output_layout(system, :Cost) # Returns "wide"
get_output_layout(system, :Flow) # Returns "long"
get_output_layout(system, :Other) # Returns "long" with warning
get_value
MacroEnergy.get_value
— Functionget_value(dict::AbstractDict, keys::Vector{Symbol})
Get the value from a dictionary based on a sequence of keys.
Arguments
dict::AbstractDict
: The dictionary from which to retrieve the value.keys::Vector{Symbol}
: The sequence of keys to traverse the dictionary.
Returns
- The value retrieved from the dictionary based on the given keys.
Examples
dict = Dict(:a => Dict(:b => 1, :c => Dict(:b => 2)))
get_value(dict, [:a, :b]) # returns 1
get_value(dict, [:a, :c, :b]) # returns 2
get_value_and_keys
MacroEnergy.get_value_and_keys
— Functionget_value_and_keys(dict::AbstractDict, target_key::Symbol, keys=Symbol[])
Recursively searches for a target key in a dictionary and returns a list of tuples containing the value associated with the target key and the keys leading to it. This function is used to replace the path to a timeseries file with the actual vector of data.
Arguments
dict::AbstractDict
: The (nested) dictionary to search in.target_key::Symbol
: The key to search for.keys=Symbol[]
: (optional) The keys leading to the current dictionary.
Returns
value_keys
: A list of tuples, where each tuple contains - the value associated with the target key - the keys leading to it in the nested dictionary.
Examples
dict = Dict(:a => Dict(:b => 1, :c => Dict(:b => 2)))
get_value_and_keys(dict, :b) # returns [(1, [:a, :b]), (2, [:a, :c, :b])]
Where the first element of the tuple is the value of the key :b and the second element is the list of keys to reach that value.
filter_edges_by_asset_type!
MacroEnergy.filter_edges_by_asset_type!
— Functionfilter_edges_by_asset_type!(edges::Vector{AbstractEdge}, asset_type::Union{Symbol,Vector{Symbol}}, edge_asset_map::Dict{Symbol,Base.RefValue{<:AbstractAsset}})
Filter edges and their associated assets by asset type.
Arguments
edges::Vector{AbstractEdge}
: Edges to filterasset_type::Union{Symbol,Vector{Symbol}}
: Target asset type(s)edge_asset_map::Dict{Symbol,Base.RefValue{<:AbstractAsset}}
: Mapping of edges to assets
Effects
- Modifies
edges
in-place to keep only edges matching the asset type - Modifies
edge_asset_map
to keep only matching assets
Throws
ArgumentError
: If none of the requested asset types are found in the system
Example
filter_edges_by_asset_type!(edges, :Battery, edge_asset_map)
filter_edges_by_commodity!
MacroEnergy.filter_edges_by_commodity!
— Functionfilter_edges_by_commodity!(edges::Vector{AbstractEdge}, commodity::Union{Symbol,Vector{Symbol}}, edge_asset_map::Dict{Symbol,Base.RefValue{<:AbstractAsset}}=Dict{Symbol,Base.RefValue{<:AbstractAsset}}())
Filter the edges by commodity and update the edgeassetmap to match the filtered edges (optional).
Arguments
edges::Vector{AbstractEdge}
: The edges to filtercommodity::Union{Symbol,Vector{Symbol}}
: The commodity to filter byedge_asset_map::Dict{Symbol,Base.RefValue{<:AbstractAsset}}
: The edgeassetmap to update (optional)
Effects
- Modifies
edges
in-place to keep only edges matching the commodity type - If
edge_asset_map
is provided, filters it to match remaining edges
Example
filter_edges_by_commodity!(edges, :Electricity)
filter_edges_by_commodity!(edges, [:Electricity, :NaturalGas], edge_asset_map)
find_available_path
MacroEnergy.find_available_path
— Functionfind_available_path(path::String, basename::String="results"; max_attempts::Int=999)
Choose an available output directory with the name "basename_<number>" by appending incremental numbers to the base path.
Arguments
path::String
: Base path for the output directory.basename::String
: Base name of the output directory.max_attempts::Int
: Maximum number of attempts to find an available directory (default is 999).
Returns
String
: Full path to the chosen output directory.
The function first expands the given path to its full path and then attempts to find an available directory by appending incremental numbers (e.g., "basename001", "basename002") up to max_attempts
times. If an available directory is found, it returns the full path to that directory. If no available directory is found after max_attempts
attempts, it raises an error.
Example
julia> path = "path/to/output"
julia> output_path = find_available_path(path)
# Returns "path/to/output/results_001" or "path/to/output/results_002" etc.
find_node
MacroEnergy.find_node
— Functionfind_node(nodes_list::Vector{Union{Node, Location}}, id::Symbol, commodity::Union{Missing,DataType}=missing)
Search for a node with the specified id
and optional commodity
type in a list of nodes and locations.
Arguments
nodes_list
: Vector of nodes and locations to search throughid
: Symbol representing the ID of the node to findcommodity
: Optional DataType specifying the commodity type of the node (default: missing)
Returns
- The found node if it exists
- Throws an error if no matching node is found
Examples
# Find a node by ID only
node = find_node(system.locations, :co2_sink)
id
MacroEnergy.id
— Functionid(v::AbstractVertex)
Get the unique identifier (ID) of a vertex.
Arguments
v
: A vertex object that is a subtype of AbstractVertex (i.e.,Node
,Storage
,Transformation
)
Returns
- A Symbol representing the vertex's unique identifier
Examples
vertex_id = id(elec_node)
id(asset::AbstractAsset)
Get the unique identifier (ID) of an asset.
Arguments
asset
: An asset object that is a subtype of AbstractAsset
Returns
- A Symbol representing the asset's unique identifier
Examples
thermal_plant = get_asset_by_id(system, :SE_natural_gas)
asset_id = id(thermal_plant) # Returns the ID of the thermal plant
json_to_csv
MacroEnergy.json_to_csv
— Functionjson_to_csv(json_data::AbstractDict{Symbol, Any}, vec_data::VectorData=VectorData(), nesting_str::AbstractString="--")
Convert a JSON object to a CSV file. The Dict should contain a single
asset described by :type, :instance_data, and possibly :global_data fields.
# Arguments
- `json_data`: The JSON object to convert.
- `vec_data`: The VectorData object to store the timeseries or other vector data in.
- `nesting_str`: The string used to denote nested properties.
# Returns
- A vector of OrderedDicts containing the data for each instance
location_ids
MacroEnergy.location_ids
— Functionlocation_ids(system::System)
Get a vector of the IDs of all locations in the system.
Arguments
system
: A System object containing various locations
Returns
- A vector of Symbols representing the IDs of all locations in the system
Examples
ids = location_ids(system)
print_struct_info
MacroEnergy.print_struct_info
— Functionprint_struct_info(asset::AbstractAsset)
Print fields and types of a given asset.
Arguments
asset
: An asset object that is a subtype of AbstractAsset
Examples
thermal_plant = get_asset_by_id(system, :SE_natural_gas_fired_combined_cycle_1)
print_struct_info(thermal_plant) # Prints the fields and types of the asset
reshape_wide
MacroEnergy.reshape_wide
— Functionreshape_wide(df::DataFrame; variable_col::Symbol=:variable, value_col::Symbol=:value)
Reshape a DataFrame from long to wide format.
Arguments
df::DataFrame
: Input DataFramevariable_col::Symbol
: Column name containing variable namesvalue_col::Symbol
: Column name containing values
Examples
df_long = DataFrame(id=[1,1,2,2], variable=[:a,:b,:a,:b], value=[10,30,20,40])
df_wide = reshape_wide(df_long)
reshape_wide(df::DataFrame, id_cols::Union{Vector{Symbol},Symbol}, variable_col::Symbol, value_col::Symbol)
Reshape a DataFrame from long to wide format.
Arguments
df::DataFrame
: DataFrame in long format to be reshapedid_cols::Union{Vector{Symbol},Symbol}
: Column(s) to use as identifiersvariable_col::Symbol
: Column containing variable names that will become new columnsvalue_col::Symbol
: Column containing values that will fill the new columns
Returns
DataFrame
: Reshaped DataFrame in wide format
Throws
ArgumentError
: If required columns are not present in the DataFrame
Examples
df_wide = reshape_wide(df, :year, :variable, :value)
reshape_long
MacroEnergy.reshape_long
— Functionreshape_long(df::DataFrame; id_cols::Vector{Symbol}=Symbol[], view::Bool=true)
Reshape a DataFrame from wide to long format.
Arguments
df::DataFrame
: Input DataFrameid_cols::Vector{Symbol}
: Columns to use as identifiers when stackingview::Bool
: Whether to return a view of the DataFrame instead of a copy
Examples
df_wide = DataFrame(id=[1,2], a=[10,20], b=[30,40])
df_long = reshape_long(df_wide, :time, :component_id, :value)
search_assets
MacroEnergy.search_assets
— Functionsearch_assets(asset_type, available_types)
Search for asset types in a list of available assets, supporting wildcards and parametric types.
Arguments
asset_type::Union{AbstractString,Vector{<:AbstractString}}
: Type(s) to search foravailable_types::Vector{<:AbstractString}
: Available asset types to search from
Returns
Tuple of two vectors:
Vector{Symbol}
: Found asset typesVector{Symbol}
: Missing asset types (only if no matches found)
Pattern Matching
Supports three types of matches:
- Exact match:
"Battery"
matches"Battery"
- Parametric match:
"ThermalPower"
matches"ThermalPower{Fuel}"
- Wildcard match:
"ThermalPower*"
matches both"ThermalPower{Fuel}"
and"ThermalPowerCCS{Fuel}"
Examples
# Available assets
assets = ["Battery", "ThermalPower{Coal}", "ThermalPower{Gas}"]
# Exact match
found, missing = search_assets("Battery", assets)
# found = [:Battery], missing = []
# Parametric match
found, missing = search_assets("ThermalPower", assets)
# found = [:ThermalPower{Coal}, :ThermalPower{Gas}], missing = []
# Wildcard match
found, missing = search_assets("ThermalPower*", assets)
# found = [:ThermalPower{Coal}, :ThermalPower{Gas}], missing = []
# Multiple types
found, missing = search_assets(["Battery", "Solar"], assets)
# found = [:Battery], missing = [:Solar]
search_commodities
MacroEnergy.search_commodities
— Functionsearch_commodities(commodities, available_commodities)
Search for commodity types in a list of available commodities, supporting wildcards and subtypes.
Arguments
commodities::Union{AbstractString,Vector{<:AbstractString}}
: Commodity type(s) to search foravailable_commodities::Vector{<:AbstractString}
: Available commodity types to search from
Returns
Tuple of two vectors:
Vector{Symbol}
: Found commodity typesVector{Symbol}
: Missing commodity types (only if no matches found)
Pattern Matching
Supports two types of matches:
- Exact match:
"Electricity"
matches only"Electricity"
- Wildcard match:
"CO2*"
matches bothCO2
and its subtypes (e.g.,CO2Captured
)
Examples
# Available commodities
commodities = ["Electricity", "CO2", "CO2Captured"]
# Exact match
found, missing = search_commodities("Electricity", commodities)
# found = [:Electricity], missing = []
# Wildcard match
found, missing = search_commodities("CO2*", commodities)
# found = [:CO2, :CO2Captured], missing = []
# Multiple types
found, missing = search_commodities(["Electricity", "Heat"], commodities)
# found = [:Electricity], missing = [:Heat]
set_value
MacroEnergy.set_value
— Functionset_value(dict::AbstractDict, keys::Vector{Symbol}, new_value)
Set the value of a nested dictionary given a list of keys.
Arguments
dict::AbstractDict
: The dictionary to modify.keys::Vector{Symbol}
: A list of keys representing the path to the value to
be modified.
new_value
: The new value to set.
Examples
dict = Dict(:a => Dict(:b => 1, :c => Dict(:b => 2)))
set_value(dict, [:a, :b], 3)
get_value(dict, [:a, :b]) # returns 3
struct_info
MacroEnergy.struct_info
— Functionstruct_info(t::Type{T}) where T
Return a vector of tuples with the field names and types of a struct.
timestepbefore
MacroEnergy.timestepbefore
— Functiontimestepbefore(t::Int, h::Int,subperiods::Vector{StepRange{Int64,Int64})
Determines the time step that is h
steps before index t
in subperiod p
with circular indexing.
collect_flow_results
MacroEnergy.collect_flow_results
— FunctionCollect flow results from all subproblems, handling distributed case.
collect_local_flows
MacroEnergy.collect_local_flows
— FunctionCollect flow results from local subproblems.
collect_distributed_flows
MacroEnergy.collect_distributed_flows
— FunctionCollect flow results from subproblems on distributed workers.
evaluate_vtheta_in_expression
MacroEnergy.evaluate_vtheta_in_expression
— FunctionEvaluate the expression expr
for a specific period using operational subproblem solutions.
Arguments
m::Model
: JuMP model containing vTHETA variables and the expressionexpr
to evaluateexpr::Symbol
: The expression to evaluatesubop_sol::Dict
: Dictionary mapping subproblem indices to their operational costssubop_indices::Vector{Int64}
: The subproblem indices to evaluate
Returns
The evaluated expression for the specified period