Non-Benders Utility Functions

    all_constraints

    MacroEnergy.all_constraintsFunction
    all_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)
    source

    all_constraints_types

    MacroEnergy.all_constraints_typesFunction
    all_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)
    source

    asset_ids

    MacroEnergy.asset_idsFunction
    asset_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 from
    • source::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
    source

    balance_ids

    MacroEnergy.balance_idsFunction
    balance_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)
    source

    balance_data

    MacroEnergy.balance_dataFunction
    balance_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 AbstractVertex
    • i: 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)
    source

    create_output_path

    MacroEnergy.create_output_pathFunction
    create_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 configuration
    • path::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
    source

    ensure_duals_available!

    MacroEnergy.ensure_duals_available!Function
    ensure_duals_available!(model::Model)

    Ensure that dual values are available in the model. If the model has integer variables and duals are not available, fixes the integer variables and re-solves the LP model to compute duals.

    Arguments

    • model::Model: The JuMP model to ensure duals for

    Throws

    • ErrorException: If the model is not solved and feasible or if the dual values are not

    available after linearization

    Notes

    • This function modifies the model in-place by fixing integer and binary variables to their

    current values.

    • The model is solved again in silent mode to avoid redundant output
    source

    get_asset_by_id

    MacroEnergy.get_asset_by_idFunction
    get_asset_by_id(system::System, id::Symbol)

    Find an asset in the system by its ID.

    Arguments

    • system: A System object containing various assets
    • id: 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)
    source

    get_assets_sametype

    MacroEnergy.get_assets_sametypeFunction
    get_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 assets
    • asset_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})
    source

    get_asset_types

    MacroEnergy.get_asset_typesFunction
    get_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
    source

    get_balance

    MacroEnergy.get_balanceFunction
    get_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 AbstractVertex
    • i: 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)
    source

    get_constraint_by_type

    MacroEnergy.get_constraint_by_typeFunction
    get_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 AbstractVertex
    • constraint_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)
    source

    get_component_by_fieldname

    MacroEnergy.get_component_by_fieldnameFunction
    get_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 AbstractAsset
    • fieldname: Symbol representing the field name of the component to get (i.e., fieldname of the asset struct)

    Returns

    • The component object stored in the specified field

    Examples

    elec_edge = get_component_by_fieldname(thermal_plant, :elec_edge)
    source

    get_component_ids

    MacroEnergy.get_component_idsFunction
    get_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)
    source

    get_component_by_id

    MacroEnergy.get_component_by_idFunction
    get_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 AbstractAsset
    • component_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)
    source

    get_edges

    MacroEnergy.get_edgesFunction
    get_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 or assets: An asset object or vector of assets that are subtypes of AbstractAsset
    • return_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)
    source

    get_output_layout

    MacroEnergy.get_output_layoutFunction
    get_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 settings
    • variable::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:

    1. Global string setting:

      settings = (OutputLayout="wide",)  # Same layout for all variables
    2. Per-variable settings using NamedTuple:

      settings = (OutputLayout=(Cost="wide", Flow="long"),)
    3. 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
    source

    get_value

    MacroEnergy.get_valueFunction
    get_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
    source

    get_value_and_keys

    MacroEnergy.get_value_and_keysFunction
    get_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.

    source

    filter_edges_by_asset_type!

    MacroEnergy.filter_edges_by_asset_type!Function
    filter_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 filter
    • asset_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)
    source

    filter_edges_by_commodity!

    MacroEnergy.filter_edges_by_commodity!Function
    filter_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 filter
    • commodity::Union{Symbol,Vector{Symbol}}: The commodity to filter by
    • edge_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)
    source

    find_available_path

    MacroEnergy.find_available_pathFunction
    find_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.
    source

    find_node

    MacroEnergy.find_nodeFunction
    find_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 through
    • id: Symbol representing the ID of the node to find
    • commodity: 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)
    source

    id

    MacroEnergy.idFunction
    id(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)
    source
    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
    source

    json_to_csv

    MacroEnergy.json_to_csvFunction
    json_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
    source

    location_ids

    MacroEnergy.location_idsFunction
    location_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)
    source
    MacroEnergy.print_struct_infoFunction
    print_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
    source

    reshape_wide

    MacroEnergy.reshape_wideFunction
    reshape_wide(df::DataFrame; variable_col::Symbol=:variable, value_col::Symbol=:value)

    Reshape a DataFrame from long to wide format.

    Arguments

    • df::DataFrame: Input DataFrame
    • variable_col::Symbol: Column name containing variable names
    • value_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)
    source
    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 reshaped
    • id_cols::Union{Vector{Symbol},Symbol}: Column(s) to use as identifiers
    • variable_col::Symbol: Column containing variable names that will become new columns
    • value_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)
    source

    reshape_long

    MacroEnergy.reshape_longFunction
    reshape_long(df::DataFrame; id_cols::Vector{Symbol}=Symbol[], view::Bool=true)

    Reshape a DataFrame from wide to long format.

    Arguments

    • df::DataFrame: Input DataFrame
    • id_cols::Vector{Symbol}: Columns to use as identifiers when stacking
    • view::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)
    source

    search_assets

    MacroEnergy.search_assetsFunction
    search_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 for
    • available_types::Vector{<:AbstractString}: Available asset types to search from

    Returns

    Tuple of two vectors:

    1. Vector{Symbol}: Found asset types
    2. Vector{Symbol}: Missing asset types (only if no matches found)

    Pattern Matching

    Supports three types of matches:

    1. Exact match: "Battery" matches "Battery"
    2. Parametric match: "ThermalPower" matches "ThermalPower{Fuel}"
    3. 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]
    source

    search_commodities

    MacroEnergy.search_commoditiesFunction
    search_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 for
    • available_commodities::Vector{<:AbstractString}: Available commodity types to search from

    Returns

    Tuple of two vectors:

    1. Vector{Symbol}: Found commodity types
    2. Vector{Symbol}: Missing commodity types (only if no matches found)

    Pattern Matching

    Supports two types of matches:

    1. Exact match: "Electricity" matches only "Electricity"
    2. Wildcard match: "CO2*" matches both CO2 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]
    Note

    Wildcard searches check against registered commodity types in MacroEnergy.jl.

    source

    set_value

    MacroEnergy.set_valueFunction
    set_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
    source

    set_constraint_dual!

    MacroEnergy.set_constraint_dual!Function
    set_constraint_dual!(constraint::BalanceConstraint, v::AbstractVertex)

    Extract and store dual values from a BalanceConstraint for all balance equations on a given vertex.

    Arguments

    • constraint::BalanceConstraint: The balance constraint to set the dual values for
    • v::AbstractVertex: The vertex containing the balance constraint

    Returns

    • nothing. The dual values are stored in the constraint_dual field of the constraint as a Dict mapping balance equation IDs (Symbol) to vectors of dual values (Vector{Float64}).

    This function extracts dual values from the constraint reference for all balance equations defined on the vertex (e.g., node or transformation) and stores them in a dictionary in the constraint_dual field.

    source

    struct_info

    timestepbefore

    MacroEnergy.timestepbeforeFunction
    timestepbefore(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.

    source

    collect_flow_results

    collect_local_flows

    collect_distributed_flows

    evaluate_vtheta_in_expression

    MacroEnergy.evaluate_vtheta_in_expressionFunction

    Evaluate the expression expr for a specific period using operational subproblem solutions.

    Arguments

    • m::Model: JuMP model containing vTHETA variables and the expression expr to evaluate
    • expr::Symbol: The expression to evaluate
    • subop_sol::Dict: Dictionary mapping subproblem indices to their operational costs
    • subop_indices::Vector{Int64}: The subproblem indices to evaluate

    Returns

    The evaluated expression for the specified period

    source

    Benders Utility Functions

    populate_slack_vars_from_subproblems!

    MacroEnergy.populate_slack_vars_from_subproblems!Function
    populate_slack_vars_from_subproblems!(
        period::System,
        slack_vars::Dict{Tuple{Symbol,Symbol}, <:AbstractDict}
    )

    Populate slack variables from Benders subproblems back into the planning problem system.

    Converts collected slack variable dictionaries back to DenseAxisArray format and assigns them to the appropriate nodes in the planning problem.

    Arguments

    • period::System: The planning problem system
    • slack_vars::Dict{Tuple{Symbol,Symbol}, <:AbstractDict}: Dictionary mapping (nodeid, slackvars_key) to slack variable data

    Returns

    • nothing
    source

    collect_distributed_policy_slack_vars

    MacroEnergy.collect_distributed_policy_slack_varsFunction
    collect_distributed_policy_slack_vars(bd_results::BendersResults)

    Collect policy slack variables from distributed Benders subproblems across multiple workers.

    Arguments

    • bd_results::BendersResults: Benders decomposition results containing distributed subproblems

    Returns

    • Dictionary with structure: periodindex => (nodeid, slackvarskey) => {axis_idx => value}
    source

    collect_local_slack_vars

    MacroEnergy.collect_local_slack_varsFunction
    collect_local_slack_vars(subproblems_local::Vector{Dict{Any,Any}})

    Collect policy slack variables from local Benders subproblems on this worker.

    Iterates through subproblems and extracts slack variables from nodes, converting them from DenseAxisArray to dictionary format for distributed collection.

    Arguments

    • subproblems_local::Vector{Dict{Any,Any}}: Local subproblems on this worker

    Returns

    • Dictionary with structure: periodindex => (nodeid, slackvarskey) => {axis_idx => value}
    source

    merge_distributed_slack_vars_dicts

    MacroEnergy.merge_distributed_slack_vars_dictsFunction
    merge_distributed_slack_vars_dicts(
        worker_results::Vector{Dict{Int64, Dict{Tuple{Symbol,Symbol}, Dict}}}
    )

    Helper function that combines results from multiple workers where each worker returns a nested dictionary structure: periodidx => (nodeid, slackvarskey) => data_dict.

    Arguments

    • worker_results::Vector{Dict{Int64, Dict{K, Dict}}}: Vector of dictionaries from each worker

    Returns

    • Merged dictionary with structure: periodidx => (nodeid, slackvarskey) => mergeddatadict
    source

    populate_constraint_duals_from_subproblems!

    MacroEnergy.populate_constraint_duals_from_subproblems!Function
    populate_constraint_duals_from_subproblems!(
        period::System,
        constraint_duals::Dict{Symbol, Dict{Symbol, <: AbstractDict}},
        ::Type{<:AbstractTypeConstraint}
    )

    Arguments

    • period::System: The planning problem
    • constraint_duals::Dict{Symbol, Dict{Symbol, Dict}}: The collected constraint duals
    • ::Type{<:AbstractTypeConstraint}: The constraint type to prepare duals for

    Returns

    • nothing

    Moves constraint duals from collected data back into the planning problem..

    source

    collect_distributed_constraint_duals

    MacroEnergy.collect_distributed_constraint_dualsFunction
    collect_distributed_constraint_duals(
        bd_results::BendersResults,
        ::Type{BalanceConstraint}
    )

    Arguments

    • bd_results::BendersResults: Benders decomposition results containing subproblems
    • ::Type{BalanceConstraint}: The constraint type to collect duals for

    Returns

    • Dict{Int64, Dict{Symbol, Dict{Symbol, Dict}}}: A nested dictionary structure containing the constraint duals

    The returned dictionary has the following structure:

    • periodindex => nodeid => balanceid => {timeidx => dual_value}
    source

    collect_local_constraint_duals

    MacroEnergy.collect_local_constraint_dualsMethod
    collect_local_constraint_duals(
        subproblems_local::Vector{Dict{Any,Any}},
        constraint_type::Type{<:AbstractTypeConstraint}
    )

    Fallback function that throws an error if the constraint type is not supported.

    This is a generic fallback method that should be specialized for specific constraint types (e.g., BalanceConstraint). If called with an unsupported constraint type, it throws a descriptive MethodError.

    Arguments

    • subproblems_local::Vector{Dict{Any,Any}}: Local subproblems on this worker
    • constraint_type::Type{<:AbstractTypeConstraint}: The constraint type to collect duals for

    Throws

    • MethodError: Always thrown to indicate the constraint type is not supported
    source
    MacroEnergy.collect_local_constraint_dualsMethod
    collect_local_constraint_duals(
        subproblems_local::Vector{<: AbstractDict{Any,Any}},
        ::Type{BalanceConstraint}
    )

    Collect BalanceConstraint duals from local subproblems on this worker.

    Arguments

    • subproblems_local::Vector{Dict{Any,Any}}: Local subproblems on this worker
    • ::Type{BalanceConstraint}: The constraint type to collect duals for

    Returns

    • Dictionary with structure: periodindex => nodeid => balanceid => {timeidx => dual_value}
    source

    merge_distributed_balance_duals

    MacroEnergy.merge_distributed_balance_dualsFunction
    merge_distributed_balance_duals(
        worker_results::Vector{<:AbstractDict{Int64, <:AbstractDict{Symbol, <:AbstractDict{Symbol, <:AbstractDict}}}}
    )

    Helper function that combines results from multiple workers where each worker returns a nested dictionary structure: periodidx => nodeid => balanceid => timedict.

    Arguments

    • worker_results::Vector{<:AbstractDict{Int64, <:AbstractDict{Symbol, <:AbstractDict{Symbol, <:AbstractDict}}}}: Vector of dictionaries from each worker

    Returns

    • Merged dictionary with structure: periodidx => nodeid => balanceid => {timeidx => dual_value}
    source

    densearray_to_dict

    dict_to_densearray