Functions for Writing the Different Results/Outputs to Separate Files

GenX.write_annual — Method
write_annual(fullpath::AbstractString, dfOut::DataFrame)

Internal function for writing annual outputs.

source
GenX.write_full_time_series_reconstruction — Method

writefulltimeseriesreconstruction(path::AbstractString, setup::Dict, DF::DataFrame, name::String) Create a DataFrame with all 8,760 hours of the year from the reduced output.

This function calls full_time_series_reconstruction()`, which uses Period_map.csv to create a new DataFrame with 8,760 time steps, as well as other pre-existing rows such as "Zone". For each 52 weeks of the year, the corresponding representative week is taken from the input DataFrame and copied into the new DataFrame. Representative periods that represent more than one week will appear multiple times in the output.

Note: Currently, TDR only gives the representative periods in Period_map for 52 weeks, when a (non-leap) year is 52 weeks + 24 hours. This function takes the last 24 hours of the time series and copies them to get up to all 8,760 hours in a year.

This function is called when output files with time series data (e.g. power.csv, emissions.csv) are created, if the setup key "OutputFullTimeSeries" is set to "1".

Arguments

  • path (AbstractString): Path input to the results folder
  • setup (Dict): Case setup
  • DF (DataFrame): DataFrame to be reconstructed
  • name (String): Name desired for the .csv file
source
GenX.write_fulltimeseries — Method
write_fulltimeseries(fullpath::AbstractString, dataOut::Matrix{Float64}, dfOut::DataFrame)

Internal function for writing full time series outputs. This function wraps the instructions for creating the full time series output files.

source
GenX.write_outputs — Method
write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)

Function for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.

source
GenX.write_system_env_summary — Method
write_system_env_summary(path::AbstractString)

Write a summary of the current testing environment to a YAML file. The summary includes information like the CPU name and architecture, number of CPU threads, JIT status, operating system kernel, machine name, Julia standard library path, Julia version and GenX version.

Arguments

  • path::AbstractString: The directory path where the YAML file will be written.

Output

Writes a file named env_summary.yml in the specified directory.

source
GenX.choose_output_dir — Method
choose_output_dir(pathinit)

Avoid overwriting (potentially important) existing results by appending to the directory name\n Checks if the suggested output directory already exists. While yes, it appends _1, _2, etc till an unused name is found

source
GenX.dftranspose — Method

df = dftranspose(df::DataFrame, withhead::Bool)

Returns a transpose of a Dataframe.

source

Write Status

GenX.write_status — Method
write_status(path::AbstractString, inputs::Dict, EP::Model)

Function for writing the final solve status of the optimization problem solved.

source
GenX.write_status_benders — Method
write_status_benders(path::AbstractString, inputs::Dict, setup::Dict, benders_results::NamedTuple)

Function for writing the final status of a Benders decomposition run.

Unlike the monolithic case, there is no single JuMP model whose termination_status describes the run: the planning problem is repeatedly re-solved and only the algorithm's bounds describe how the decomposition terminated. The status is therefore derived from the Benders bounds and the stopping criteria in setup:

  • MOI.OPTIMAL if the final relative gap (UB - LB) / |LB| is within setup[:ConvTol]
  • MOI.TIME_LIMIT if the elapsed CPU time reached setup[:MaxCpuTime]
  • MOI.ITERATION_LIMIT if the iteration count reached setup[:MaxIter]
  • MOI.OTHER_LIMIT otherwise (terminated for some other reason without converging)

Objval is the best upper bound (the cost of the incumbent planning solution plus the operational cost it implies), and Objbound is the final lower bound.

source

Write CO_2 Cap

GenX.write_co2_cap — Function
write_co2_cap(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting carbon price associated with carbon cap constraints.

source

Write Costs

GenX._accumulate_fixed! — Method

Split one fixed-cost component into its investment and fixed O&M parts and accumulate all four views.

A fixed-cost expression is investment + fixed O&M, and the two need different treatment when reporting a multi-stage run, so they have to be separated. Fixed O&M is recoverable because it is always rate * capacity; investment is then whatever remains.

Both parts are recovered to annual terms first, undoing the scaling configure_multi_stage_inputs applied, and then re-scaled:

  • fix the model's own value, used as-is for single-stage runs
  • fix_fom annual fixed O&M
  • fix_inv_A investment over the annuities falling inside the horizon
  • fix_inv_P investment as an undiscounted cash flow

Under perfect foresight the investment field already holds the overnight capital cost, so dividing by the annuity factor recovers the annuity. Under myopic it holds a single year's annuity, so no division is needed and multiplying by the annuity factor adds back the payments the myopic objective never saw. That add-back is what makes the two modes comparable.

source
GenX._investment_views — Method
_investment_views(scaled, A, P, myopic) -> (discounted, undiscounted)

Turn one investment cost as the model holds it into the two reported views.

A is the annuity factor and P the count of payments falling inside the horizon, both for the item being priced.

Under perfect foresight the model already holds the overnight capital cost, so dividing by A recovers the annual annuity. Under myopic the model holds a single year's annuity, so no division is needed, and multiplying by A adds back the payments the myopic objective never charged.

Used for both resource fixed costs and transmission expansion, which differ only in what they iterate over.

source
GenX.assemble_costs — Method
assemble_costs(bd::NamedTuple, inputs::Dict, setup::Dict; basis::Symbol = :model)

Turn a cost_breakdown into the costs.csv table: a Costs column of row names, a Total column, and one column per zone.

basis selects how stage costs are expressed, and only applies to multi-stage runs:

  • :model – the model's own values, used for single-stage runs
  • :discounted – present value at the start of the modeling horizon, which is what the objective function weighs
  • :undiscounted – cash flows over the stage, with no time value

Rows without a per-resource attribution (cUnmetRsv, cNetworkExp, cUnmetPolicyPenalty) and the cGridConnection memo row are written as empty cells in the zone columns, matching the system-wide nature of those terms. Empty keeps the column numeric when read back, which a string placeholder would not.

ParameterScale is applied once, to every numeric cell, at the end.

source
GenX.cost_breakdown — Method
cost_breakdown(EP::Model, inputs::Dict, setup::Dict)

Collect the solved cost terms that make up costs.csv, in model units and before any scaling.

Costs that can be attributed to a resource are returned as vectors indexed by resource id, so that the system total is the sum of the vector and a zone's value is the sum over the resources in that zone. This is what makes the zone columns add up to the Total column by construction, rather than by two independent accumulations that can drift apart.

Costs with no per-resource attribution are returned as scalars (unmet_rsv, netexp, policy_penalty) or per-zone vectors (nse).

Returns a NamedTuple; see assemble_costs for how it becomes a table.

source
GenX.write_costs — Method
write_costs(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the costs pertaining to the objective function (fixed, variable O&M etc.).

source

Write Fuel Consumption

GenX.write_fuel_consumption — Function
write_fuel_consumption(path::AbstractString, inputs::Dict, setup::Dict, EP::Model).

Write fuel consumption of each power plant.

source

Write Emissions

GenX.write_emissions — Method
write_emissions(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting time-dependent CO$_2$ emissions by zone.

source

Write Capacities

GenX.write_capacity — Method
write_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model))

Function for writing the diferent capacities for the different generation technologies (starting capacities or, existing capacities, retired capacities, and new-built capacities).

source

Write Capacity Value

GenX.capacity_reserve_margin_price — Method
capacity_reserve_margin_price(EP::Model,
                              inputs::Dict,
                              setup::Dict,
                              capres_zone::Int)::Vector{Float64}

Marginal price for capacity constraint. This is equal to the dual variable of the capacity constraint. Returns a vector, with units of USD/MW

source
GenX.write_capacity_value — Method
write_capacity_value(path::AbstractString,
                     inputs::Dict,
                     setup::Dict,
                     EP::Model)

This is the value of the derated capacities of different types of resources multiplied by the power generated by each of them

Arguments

  • path::AbstractString: Path to the directory where the file will be written.
  • inputs::Dict: Dictionary of input data.
  • setup::Dict: Dictionary of setup data.
  • EP::Model: EnergyModel object.

Results

  • A CSV file named "CapacityValue.csv" is written to the directory specified by path.
source

Write Capacity Factors

GenX.write_capacityfactor — Method
write_capacityfactor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the capacity factor of different resources. For co-located VRE-storage resources, this value is calculated if the site has either or both a solar PV or wind resource.

source
GenX.write_fusion_net_capacity_factor — Method
write_fusion_net_capacity_factor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

The "net capacity factor" for fusion plants is the ratio of the annual net output to the net time-averaged capacity. The net output is the gross output less parasitic power. The net time-averaged capacity accounts for parasitic power and average capacity due to the need to pulse the plant, if any.

source

Write Charge Values

GenX.write_charge — Method
write_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the charging energy values of the different storage technologies.

source

Write Non-served-energy

GenX.write_nse — Method
write_nse(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting non-served energy for every model zone, time step and cost-segment.

source

Write Storage State of Charge

GenX.write_storage — Method
write_storage(path::AbstractString, inputs::Dict,setup::Dict, EP::Model)

Function for writing the capacities of different storage technologies, including hydro reservoir, flexible storage tech etc.

source

Write Storage Dual

GenX.write_storagedual — Method
write_storagedual(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting dual of storage level (state of charge) balance of each resource in each time step.

source

Write Power

GenX.write_power — Method
write_power(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the different values of power generated by the different technologies in operation.

source

Write Curtailment

GenX.write_curtailment — Method
write_curtailment(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the curtailment values of the different variable renewable resources (both standalone and co-located).

source

Write Prices

GenX.locational_marginal_price — Method
locational_marginal_price(EP::Model, inputs::Dict, setup::Dict)

Marginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.

Returns a matrix of size (T, Z).
Values have units of USD/MWh
source
GenX.write_price — Method
write_price(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the power balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.

source

Write Reliability

GenX.write_reliability — Method
write_reliability(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.

source

Write Energy Revenue

GenX.write_energy_revenue — Method
write_energy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing energy revenue from the different generation technologies.

source

Write Subsidy Revenue

GenX.write_subsidy_revenue — Method
write_subsidy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting subsidy revenue earned if a generator specified Min_Cap is provided in the input file, or if a generator is subject to a Minimum Capacity Requirement constraint. The unit is $.

source

Write Operating Reserve and Regulation Revenue

GenX.write_operating_reserve_regulation_revenue — Method
write_operating_reserve_regulation_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the operating reserve and regulation revenue earned by generators listed in the input file. GenX will print this file only when operating reserve and regulation are modeled and the shadow price can be obtained from the solver. The revenues are calculated as the operating reserve and regulation contributions in each time step multiplied by the corresponding shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all operating reserve and regulation constraints. As a reminder, GenX models the operating reserve and regulation at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

source

Write Capacity Revenue

GenX.write_reserve_margin_revenue — Method
write_reserve_margin_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

source

Write Hourly Matching Revenue

GenX.write_hourly_matching_prices — Function
write_hourly_matching_prices(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the shadow price of each hourly matching constraint in each timestep. GenX will print this file only when an hourly matching requirement is modeled and the shadow price can be obtained form the solver. Each column corresponds to an hourly matching constraint, and each row corresponds to a timestep.

source
GenX.write_hourly_matching_revenue — Function
write_hourly_matching_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the hourly matching revenue earned by each generator listed in the input file. GenX will print this file only when an hourly matching requirement is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the is the total revenue from each hourly matching constraint. The revenue is calculated as the net generation in each time step multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all hourly matching constraints.

source
GenX.write_hourly_matching_slack — Function
write_hourly_matching_slack(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the value of the slack variable for each hourly matching constraint in each timestep and the total objective function cost. GenX will print this file only when an hourly matching requirement is modeled, an optional slack variable is created, and the shadow price can be obtained form the solver.

source

Write Energy Share Requirement Revenue

GenX.write_esr_revenue — Method
write_esr_revenue(path::AbstractString, inputs::Dict, setup::Dict, dfPower::DataFrame, dfESR::DataFrame, EP::Model)

Function for reporting the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.

source

Write Net Revenue

GenX.write_net_revenue — Method
write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model, dfCap::DataFrame, dfESRRev::DataFrame, dfResRevenue::DataFrame, dfChargingcost::DataFrame, dfPower::DataFrame, dfEnergyRevenue::DataFrame, dfSubRevenue::DataFrame, dfRegSubRevenue::DataFrame, dfVreStor::DataFrame, dfOpRegRevenue::DataFrame, dfOpRsvRevenue::DataFrame)

Function for writing net revenue of different generation technologies.

source

Write Co-Located VRE and Storage files

GenX.write_vre_stor — Function
write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage specific files.

source
GenX.write_vre_stor_capacity — Function
write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage capacities.

source
GenX.write_vre_stor_charge — Function
write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage charging decision variables/expressions.

source
GenX.write_vre_stor_discharge — Function
write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage discharging decision variables/expressions.

source

Write Multi-stage files

GenX.write_multi_stage_outputs — Method
write_multi_stage_outputs(stats_d::Dict, 
    outpath::String, 
    settings_d::Dict, 
    inputs_dict::Dict)

This function calls various methods which write multi-stage modeling outputs as .csv files.

Arguments:

  • stats_d: Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • outpath: String which represents the path to the Results directory.
  • settings_d: Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.
  • inputs_dict: Dictionary containing the input data for the multi-stage model.
source
GenX.write_multi_stage_costs — Function
write_multi_stage_costs(outpath::String, settings_d::Dict)

Writes costs_multi_stage.csv and costs_undiscounted_multi_stage.csv to the Results directory, stacking each stage's Total column side by side.

The per-stage files written by write_costs are already expressed in their final terms, so this function applies no further scaling. Summing a row across the stage columns of costs_multi_stage.csv therefore gives the cost over the whole modeling horizon, in present value at the start of the horizon.

  • costs_multi_stage.csv – discounted to the start of the horizon; under perfect foresight the cTotal row sums to the cost of the solution the algorithm converged on.
  • costs_undiscounted_multi_stage.csv – cash flows over each stage, with no time value.

Under myopic foresight both files include the investment annuities that fall beyond the stage being solved. The myopic objective charges only a single year of each annuity, so those payments are added back here; without that the two foresight modes would not be comparable.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
  • stats_d - Optional dictionary of dual dynamic programming bounds. When given, a warning is issued if the algorithm stopped above its convergence tolerance, since the reported costs then describe the final forward pass rather than an optimal trajectory.
source
GenX.write_multi_stage_stats — Function

writemultistagestats(outpath::String, statsd::Dict)

This function writes the file stats_multi_stage.csv. to the Results directory. This file contains the runtime, upper bound, lower bound, and relative optimality gap for each iteration of the DDP algorithm.

inputs:

  • outpath – String which represents the path to the Results directory.
  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
source
GenX.write_multi_stage_settings — Function
write_multi_stage_settings(outpath::AbstractString, settings_d::Dict)

Function for writing the multi-stage settings file to the output path for future reference.

source
GenX.write_multi_stage_network_expansion — Function
write_multi_stage_network_expansion(outpath::String, settings_d::Dict)

This function writes the file network_expansion_multi_stage.csv to the Results directory. This file contains new transmission capacities for each modeled transmission line for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_capacities_discharge — Function
write_multi_stage_capacities_discharge(outpath::String, settings_d::Dict)

This function writes the file capacities_multi_stage.csv to the Results directory. This file contains starting resource capacities from the first model stage and end resource capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_capacities_charge — Function
write_multi_stage_capacities_charge(outpath::String, settings_d::Dict)

This function writes the file capacities_charge_multi_stage.csv to the Results directory. This file contains starting resource charge capacities from the first model stage and end resource charge capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_capacities_energy — Function
write_multi_stage_capacities_energy(outpath::String, settings_d::Dict)

This function writes the file capacities_energy_multi_stage.csv to the Results directory. This file contains starting resource energy capacities from the first model stage and end resource energy capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.create_multi_stage_stats_file — Function
create_multi_stage_stats_file(outpath::String)

Create an empty CSV file in the specified output directory with the filename stats_multi_stage.csv. The file contains the columns defined in _get_multi_stage_stats_header(). The function first generates the filename and header using _get_multi_stage_stats_filename() and _get_multi_stage_stats_header() respectively. It then creates a DataFrame with column names as headers and writes it into a CSV file in the specified output directory.

Arguments

  • outpath::String: The output directory where the statistics file will be written.

Returns

  • Nothing. A CSV file is written to the outpath.
source
GenX.update_multi_stage_stats_file — Function
update_multi_stage_stats_file(outpath::String, ic::Int64, upper_bound::Float64, lower_bound::Float64, iteration_time::Float64; new_row::Bool=false)

Update a multi-stage statistics file.

Arguments

  • outpath::String: The output directory where the statistics file will be written.
  • ic::Int64: The iteration count.
  • upper_bound::Float64: The upper bound value.
  • lower_bound::Float64: The lower bound value.
  • iteration_time::Float64: The iteration time value.
  • new_row::Bool=false: Optional argument to determine whether to append a new row (if true) or update the current row (if false).

The function first checks if the file exists. If it does not, it creates a new one. Then, it reads the statistics from the existing file into a DataFrame. It calculates the relative gap based on the upper and lower bounds, and either appends a new row or updates the current row based on the new_row argument. Finally, it writes the updated DataFrame back to the file.

Returns

  • Nothing. A CSV file is updated or created at the outpath.
source

Write maintenance files

Write DCOPF files

GenX.write_angles — Function
write_angles(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the bus angles for each model zone and time step if the DC_OPF flag is activated

source

Write Settings Files

Write Allam Cycle LOX

GenX.write_allam_capacity — Function
write_allam_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

This function writes the different capacities for the Allam Cycle LOX technologies (starting capacities or, existing capacities, retired capacities, and new-built capacities) to the capacity_allam_cycle_lox.csv file.

source
GenX.write_allam_output — Function
write_allam_output(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

This function writes the power output from each component of an Allam Cycle LOX resource to the output_allam_cycle_lox.csv file.

source

Write Transmission Outputs

When discrete new lines are present (DiscreteInvestments = 1), load_network_data! gives each candidate line its own row, so the solved model has more lines than the user's Network.csv. These writers fold the expanded lines back onto the original corridors using inputs["LINE_MAP_ORIGINAL"], so the outputs are indexed by the corridors the user supplied. See DC-OPF and Transmission Expansion.

GenX.fold_lines_to_corridors — Method
fold_lines_to_corridors(inputs::Dict, data::AbstractArray)

Fold a per-line quantity from the (possibly expanded) solved network back to the original user-provided corridors by summing the rows that belong to each corridor.

When discrete-build lines are present, load_network_data! rebuilds the network so each discrete new line is its own row (see expand_discrete_build_lines), giving the solved model more lines than the user's Network.csv. LINE_MAP_ORIGINAL maps each expanded line index back to its original corridor; all the expanded lines of a corridor share the same orientation (Start_Zone/End_Zone are copied), so summing them yields the corridor total. When no rebuild occurred (LINE_MAP_ORIGINAL absent) the mapping is the identity and the data is returned unchanged.

data may be an L-vector or an L×T matrix. Returns (corridors, folded) where corridors is the sorted vector of original corridor indices used as the output Line column.

source
GenX.network_expansion_dataframe — Method
network_expansion_dataframe(inputs::Dict, setup::Dict; cont_value, disc_value)

Build the network_expansion.csv table, folding results from the (possibly expanded) per-line solve back to the original user-provided corridors.

When discrete-build lines are present, load_network_data! rebuilds the network so each discrete new line is its own row (see expand_discrete_build_lines), so the solved model has more lines than the user's Network.csv. LINE_MAP_ORIGINAL maps each expanded line index back to the original corridor index; here we use it to aggregate both the continuous reinforcement (vNEW_TRANS_CAP) and the discrete builds (vNEW_TRANS_LINES) up to one row per original corridor. When no rebuild occurred (LINE_MAP_ORIGINAL absent) the mapping is the identity, so the output is one row per line exactly as before.

cont_value(l) returns the continuous reinforcement of expanded line l (only called for l in EXPANSION_LINES); disc_value(l) returns the binary build decision of expanded line l (only called for l in DISCRETE_BUILD_LINES). Passing these as callbacks lets the monolithic and Benders writers share this logic while reading their respective solutions.

source

Write Benders Decomposition Outputs

GenX._as_time_matrix — Method
_as_time_matrix(data, nrows, ncols, name)

Coerce data into a (nrows × ncols) Matrix{Float64}, transposing if needed.

Accepts vectors (reshaped to a single row or column depending on which dimension matches), matrices in either orientation, or any Array-convertible type. Raises DimensionMismatch if the data cannot be unambiguously mapped to the target shape. name is used only in error messages.

source
GenX._slice_time_series — Method
_slice_time_series(data, time_columns)

Slice data along its time axis using time_columns.

For a 1-D array returns data[time_columns]; for a 2-D array returns data[:, time_columns]. Converts to a plain Array first to handle JuMP DenseAxisArray inputs.

source
GenX._subproblem_time_columns — Method
_subproblem_time_columns(inputs, subproblem, local_T)

Return the global time-step range corresponding to a single subproblem.

Uses subproblem[:subproblem_index] and inputs["hours_per_subperiod"] to map local time indices 1:local_T to their position in the full annual time series. Returns 1:local_T when either field is absent (single-period or non-decomposed case).

source
GenX._subproblem_zonal_operational_costs — Method
_subproblem_zonal_operational_costs(EP, inputs, setup)

Compute per-zone operational costs from a solved subproblem EP, as three Z-length vectors (cvar, cnse, cstart) in raw model units (scaling applied by the cost writer).

Mirrors the per-zone loop of the monolithic write_costs:

  • cvar — generation/discharge (eCVar_out), storage charging (eCVar_in), flexible demand (eCVarFlex_in), co-located VRE+storage, and Allam-cycle (eCVar_Allam) VOM.
  • cnse — non-served energy (eCNSE[:, :, z]).
  • cstart — non-fuel startup O&M (eCStart, eCStart_Allam). Startup fuel is excluded here and added by the cost writer from the per-plant fuel_cost_start.

Each per-zone sum is over the subproblem's time slice; summing across subproblems yields the annual per-zone value. Component sets absent from the model contribute zero.

source
GenX._vre_stor_zonal_var_om — Method
_vre_stor_zonal_var_om(EP, inputs, z)

Zone-z variable O&M for co-located VRE+storage resources in a subproblem EP.

Mirrors the VRE-storage block of the monolithic write_costs per-zone loop: solar/wind output VOM (eCVarOutSolar/eCVarOutWind) plus asymmetric DC/AC charge/discharge VOM. Returns raw model units; empty when the model has no VRE-storage resources.

source
GenX.collect_benders_output_bundle — Method
collect_benders_output_bundle(inputs, setup, subproblems)

Collect all operational output arrays from solved subproblems into a single NamedTuple.

Dispatches to collect_distributed_output_bundle when subproblems is a DArray (multi-worker run) or get_local_output_bundle otherwise.

source
GenX.collect_distributed_output_bundle — Method
collect_distributed_output_bundle(inputs, setup, subproblems)

Collect and concatenate output bundles from all workers into a single NamedTuple.

Fetches get_local_output_bundle from each worker in parallel, then reduces each time-series field with hcat (concatenating representative periods along the time axis) and each scalar/annual field with +. Returns a single bundle with the same structure as get_local_output_bundle.

source
GenX.get_local_output_bundle — Method
get_local_output_bundle(inputs, setup, subproblems_local)

Extract and assemble all output arrays from the subproblems on a single worker.

Iterates over subproblems_local, extracting power dispatch, emissions, charge, storage, curtailment, NSE, transmission flows and losses, fuel consumption, dual-based prices, storage duals, and unit commitment decisions from each solved JuMP model. Time-series arrays are concatenated along the time axis (representative periods ordered by subproblem_index) to produce full-year matrices.

Returns a NamedTuple with all operational output arrays needed by the write functions, plus has_subproblem_duals indicating whether LP duals were available.

source
GenX.write_benders_output — Method
write_benders_output(benders_results, outpath, setup, inputs, planning_problem, subproblems)

Write all Benders decomposition outputs to outpath.

Orchestrates the full output pipeline: convergence history, capacity, network expansion, policy requirements, costs, operational time series (power, charge, storage, curtailment, NSE, power balance, emissions, fuel consumption, transmission), capacity factors, shadow-price-based outputs (LMPs, reliability prices, storage duals, energy revenue, charging costs), unit commitment decisions, and planning problem duals. Each output is guarded by the corresponding key in setup["WriteOutputsSettingsDict"]; outputs default to enabled when the key is absent.

If the planning problem has no solver values (e.g. the algorithm did not converge), only the status file and convergence CSV are written and the function returns early.

source
GenX.write_capacity_benders — Method
write_capacity_benders(path, inputs, setup, planning_problem, planning_sol)

Write capacity.csv for a Benders run using the incumbent planning solution directly.

Capacity quantities are evaluated by substituting the best-incumbent variable values from planning_sol.values into the planning-problem variables and capacity expressions (value(v -> planning_sol.values[name(v)], ...)), so the output reflects the same first-stage solution as the dispatch outputs regardless of the planning-problem model's post-Benders solve state. This mirrors the monolithic write_capacity column-for-column except that CapacityConstraintDual is omitted: that column is a shadow price, which is not available from planning_sol (and is not reliably recoverable from the cut-laden master). It can be reintroduced once a trustworthy planning dual is available.

source
GenX.write_capacityfactor_benders — Method
write_capacityfactor_benders(path, inputs, setup, benders_bundle, planning_problem)

Write capacity factors using power output from subproblems and installed capacity from the planning problem.

source
GenX.write_charge — Method
write_charge(path, inputs, setup, charge, charge_ids)

Write charging power to charge.csv for the subset of resources indexed by charge_ids.

charge is a (length(charge_ids) × T) matrix of unscaled values.

source
GenX.write_charging_cost_benders — Method
write_charging_cost_benders(path, inputs, setup, benders_bundle)

Write annual charging costs for storage and flexible demand resources using subproblem LMPs.

source
GenX.write_co2_cap_benders — Method
write_co2_cap_benders(path, inputs, setup, planning_problem)

Write CO2 prices from the Benders planning problem (constraint cCO2Emissions_systemwide_planning).

source
GenX.write_co2_emissions_plant — Method
write_co2_emissions_plant(path, inputs, setup, emissions_plant)

Write per-plant annual CO2 emissions to emissions_plant.csv.

emissions_plant is a (G × T) matrix of unscaled emissions values. Scale factor is applied before computing the annual weighted sum. Time-series columns are written when setup["WriteOutputs"] != "annual".

source
GenX.write_curtailment_benders — Method
write_curtailment_benders(path, inputs, setup, curtailment)

Write VRE curtailment to curtailment.csv.

curtailment is a (G × T) matrix of unscaled curtailment values (available generation minus dispatched generation for VRE resources, zero for others).

source
GenX.write_emissions_benders — Method
write_emissions_benders(path, inputs, setup, emissions_by_zone)

Write total CO2 emissions aggregated by zone to emissions.csv.

emissions_by_zone is a (Z × T) matrix of unscaled zone-level emissions. Annual or time-series output is selected by setup["WriteOutputs"].

source
GenX.write_fuel_consumption_benders — Method
write_fuel_consumption_benders(path, inputs, setup, benders_bundle)

Write all fuel consumption outputs.

Calls write_fuel_consumption_plant_benders, write_fuel_consumption_ts_benders (when time-series output is requested), and write_fuel_consumption_tot_benders.

source
GenX.write_fuel_consumption_plant_benders — Method
write_fuel_consumption_plant_benders(path, inputs, setup, benders_bundle)

Write per-plant annual fuel costs and heat input to Fuel_cost_plant.csv.

Includes multi-fuel breakdown columns when inputs["MULTI_FUELS"] is non-empty.

source
GenX.write_fuel_consumption_ts_benders — Method
write_fuel_consumption_ts_benders(path, inputs, setup, benders_bundle)

Write per-plant hourly fuel consumption time series to FuelConsumption_plant_MMBTU.csv.

Only called when setup["WriteOutputs"] != "annual". Optionally reconstructs the full time series when OutputFullTimeSeries is enabled.

source
GenX.write_nse_benders — Method
write_nse_benders(path, inputs, setup, nse)

Write non-served energy (NSE) by segment and zone to nse.csv.

nse is a (SEG*Z × T) matrix laid out as segments cycling within zones. Annual or time-series output is selected by setup["WriteOutputs"].

source
GenX.write_nw_expansion_benders — Method
write_nw_expansion_benders(path, inputs, setup, planning_problem, planning_sol)

Write network_expansion.csv for a Benders run using the incumbent planning solution.

Transmission reinforcement (vNEW_TRANS_CAP) is a first-stage variable, so its value is read from planning_sol by substituting the incumbent variable values into the planning-problem variable (value(v -> planning_sol.values[name(v)], ...)) — no solved model state required. Mirrors the monolithic write_nw_expansion.

source
GenX.write_power — Method
write_power(path, inputs, setup, power)

Write per-resource power output to power.csv.

power is a (G × T) matrix of unscaled dispatch values. The scale factor is applied, annual weighted sums are computed, and time-series columns are included when setup["WriteOutputs"] != "annual".

source
GenX.write_power_balance_benders — Method
write_power_balance_benders(path, inputs, setup, benders_bundle)

Write the zonal power balance decomposition to power_balance.csv.

Assembles the (Lcomp*Z × T) power-balance matrix from the operational time series stored in benders_bundle, covering generation, storage discharge/charge, flexible demand, NSE, transmission net exports and losses, demand, and optional electrolyzer, VRE-storage, and fusion components.

source
GenX.write_price_benders — Method
write_price_benders(path, inputs, setup, price)

Write locational marginal prices (LMPs) from Benders subproblem duals. price is a (Z × T) matrix already scaled ($/MWh) and divided by period weights.

source
GenX.write_reliability_benders — Method
write_reliability_benders(path, inputs, setup, reliability)

Write reliability prices (shadow prices on NSE capacity constraints) from Benders subproblem duals. reliability is a (Z × T) matrix already scaled ($/MWh) and divided by period weights.

source
GenX.write_storage_benders — Method
write_storage_benders(path, inputs, setup, stored, stored_ids)

Write state-of-charge values to storage.csv for resources indexed by stored_ids.

stored is a (length(stored_ids) × T) matrix of unscaled state-of-charge values.

source
GenX.write_storagedual_benders — Method
write_storagedual_benders(path, inputs, setup, storagedual)

Write storage state-of-charge balance duals from Benders subproblem LPs. storagedual is a (G × T) matrix with duals divided by period weights (scale applied here).

source
GenX.write_transmission_flows_benders — Method
write_transmission_flows_benders(path, inputs, setup, flow)

Write line-level power flows to flow.csv.

flow is a (L × T) matrix of unscaled flow values. Annual or time-series output is selected by setup["WriteOutputs"].

source
GenX.write_transmission_losses_benders — Method
write_transmission_losses_benders(path, inputs, setup, tlosses)

Write line-level transmission losses to tlosses.csv.

tlosses is a (L × T) matrix of unscaled loss values. Annual or time-series output is selected by setup["WriteOutputs"].

source
GenX.write_ucommit_benders — Method
write_ucommit_benders(path, inputs, setup, data, filename)

Write unit commitment, startup, or shutdown decisions (generic helper). data is a (COMMIT_count × T) matrix of values.

source
GenX.write_planning_problem_costs — Function
write_planning_problem_costs(path, inputs, setup, benders_results, planning_problem, benders_bundle=nothing)

Write the Benders cost breakdown to planning_problem_costs.csv.

First-stage (planning) costs — total fixed cost (cFix), network expansion cost (cNetworkExp), and unmet planning policy penalty (cUnmetPlanningPolicyPenalty) — are evaluated against the best Benders planning solution stored in benders_results.planning_sol (no re-solve required, so they are valid even when the master model holds no solver values).

When benders_bundle is supplied, the operational (second-stage) costs aggregated from the solved subproblems are added as additional rows, mirroring the monolithic write_costs: variable O&M (cVar), fuel (cFuel), non-served energy (cNSE), and startup (cStart, non-fuel startup O&M plus startup fuel). In that case cTotal is the actual cost of the incumbent design (fixed + network + operational), which equals the Benders upper bound. When benders_bundle is nothing (e.g. the no-values early-return path) only the first-stage rows are written and cTotal is taken from the master objective value(eObj).

Per-zone columns (Zone1 … ZoneZ) are appended when multiple zones exist. Fixed costs are always broken out by zone; with a bundle the operational costs are too (matching the monolithic per-zone layout). System-wide rows without a per-resource attribution — cNetworkExp and cUnmetPlanningPolicyPenalty — are written as empty cells in each zone column.

source