Outputs

Contents

Overview | Directory Structure | Settings | Output Files | MacroEnergy API | See Also

Overview

After solving a Macro model, results are automatically written to disk by write_outputs. The output files are CSV-format tabular data that describe the optimal capacity decisions, operational dispatch, and costs of every asset in the system.

Outputs are organized into one results directory per modeled period. Within each directory, each output type is stored in its own file. The files use a consistent long format by default (one row per observation, with metadata columns identifying the asset and time step), which makes them easy to filter and join using standard data tools. A wide format is also available via the OutputLayout setting, which allows pivoting of time steps or variables into columns for easier human readability.

All write functions are called automatically when you run run_case (or solve_case when using Myopic as solution algorithm). You can also call each function individually to re-export a specific output after modifying a solved system.

Output Directory Structure

Single-Period Models

For a single-period model, results are written inside a two-level directory structure. An outer directory is created from the OutputDir setting (default results with a numeric suffix), and an inner results/ directory is created inside it for the actual output files:

my_case/
├── case_settings.json
├── settings/
│   └── macro_settings.json
├── system/
│   └── ...
├── results_001/              ← outer directory (non-overwrite default)
│   ├── settings.json         ← case-level settings snapshot
|   ├── my_case.log           ← copied here after the run
│   └── results/              ← all output files written here
│       ├── capacity.csv
│       ├── costs.csv
│       ├── flows.csv
│       └── ...

When OverwriteResults = true, the outer directory name is exactly OutputDir (default results) with no suffix:

my_case/
├── results/                  ← outer directory (overwrite mode)
│   ├── settings.json
│   ├── my_case.log
│   └── results/              ← output files
│       ├── capacity.csv
│       └── ...

Multi-Period Models

For multi-period (planning) models, the same outer directory is created, and each planning period gets its own results_period_N/ subdirectory inside it:

my_case/
├── case_settings.json
├── my_case.log               ← written here during the run
└── results_001/                  ← outer directory
    ├── settings.json             ← case-level settings snapshot
    ├── my_case.log               ← copied here after the run
    ├── results_period_1/         ← period 1 outputs
    │   ├── capacity.csv
    │   └── ...
    └── results_period_2/         ← period 2 outputs
        ├── capacity.csv
        └── ...

Overwrite Behavior

By default (OverwriteResults = false), Macro will not overwrite an existing outer results directory. Instead, it appends an incremental numeric suffix: results_001, results_002, etc. This is controlled by the OverwriteResults and OutputDir settings in macro_settings.json.

Settings snapshot

A settings.json file is always written inside the outer directory (e.g., results_001/settings.json) recording the case_settings and system_settings used for the run. See Settings Output for details.

Output Settings

The following settings in macro_settings.json control the behavior of the output files.

Layout and Format

SettingTypeDefaultDescription
OutputLayoutString or JSON Object"long"Output layout for tabular files. "long" stacks all observations as rows; "wide" pivots time steps or variables to columns. Can be set globally with a single string, or per-file as a JSON object (see below).
OverwriteResultsBoolfalseIf true, overwrite the output directory on each run. If false, append _001, _002, … suffixes to avoid overwriting.
OutputDirString"results"Base name for the results directory.
DualExportsEnabledBooltrueIf true, write balance_duals.csv and co2_cap_duals.csv.

Per-File Layout Control

Instead of a single string, OutputLayout can be a JSON object to control layout independently for each output type:

"OutputLayout": {
    "Capacity":        "wide",
    "Costs":           "long",
    "Flow":            "long",
    "StorageLevel":    "long",
    "Curtailment":     "long",
    "NonServedDemand": "long"
}

Supported keys: Capacity, Costs, Flow, StorageLevel, Curtailment, NonServedDemand.

Full Time Series Setting

Full time series output

The WriteFullTimeseries setting needs to be set in case_settings.json (not macro_settings.json).

SettingFileDefaultDescription
WriteFullTimeseriescase_settings.jsonfalseIf true and time-domain reduction (TDR) is used, write expanded time-series outputs covering all TotalHoursModeled hours to a full_time_series/ subdirectory.

Output Files

The table below lists all output files produced by Macro. Click the file name to go to the detailed page for that output.

Written when column

The Written when column indicates whether the file is always produced or only under specific conditions. There are three types of conditions:

  • Always — written on every successful run.
  • System content — written only when the system contains the relevant asset type or constraint (e.g., no curtailment file if there are no VRE assets).
  • Setting / algorithm — written only when a particular setting is enabled or a specific solution algorithm is used.
FileDescriptionWritten when
capacity.csvOptimal, new, retired, retrofitted, and existing capacity for every asset componentAlways
costs.csvTotal discounted system costs (fixed, variable, total)Always
undiscounted_costs.csvTotal undiscounted system costsAlways
costs_by_type.csvDiscounted cost breakdown by asset type and cost categoryAlways
costs_by_zone.csvDiscounted cost breakdown by zone and cost categoryAlways
undiscounted_costs_by_type.csvUndiscounted cost breakdown by asset type and cost categoryAlways
undiscounted_costs_by_zone.csvUndiscounted cost breakdown by zone and cost categoryAlways
flows.csvCommodity flow for every edge at every representative time stepAlways
time_weights.csvRepresentative period weights mapping each time step to its full-year equivalent hoursAlways
settings.jsonSnapshot of all case and system settings used for the runAlways
storage_level.csvState of charge for every storage component at every representative time stepSystem has storage assets
curtailment.csvCurtailed generation for VRE assets at every representative time stepSystem has VRE assets with has_capacity = true
non_served_demand.csvNon-served demand for every node with NSD variables at every representative time stepSystem has nodes with NSD variables
balance_duals.csvShadow prices of commodity balance constraints (locational marginal prices)DualExportsEnabled = true (default)
co2_cap_duals.csvShadow prices of CO₂ cap constraints (carbon prices)DualExportsEnabled = true (default)
<case_name>.logPlain-text log of all messages emitted during the runlog_to_file = true (default)
full_time_series/Expanded time-series outputs covering all TotalHoursModeled hoursWriteFullTimeseries = true and TDR used
benders_convergence.csvBenders decomposition convergence metrics per iterationBenders algorithm only

MacroEnergy API

Writing Outputs

The following functions write output files. They are called automatically by run_case/solve_case but can also be invoked individually.

FunctionFile(s) Written
write_outputsAll files (orchestrator)
write_capacitycapacity.csv
write_costscosts.csv
write_undiscounted_costsundiscounted_costs.csv
write_flowflows.csv
write_storage_levelstorage_level.csv
write_curtailmentcurtailment.csv
write_non_served_demandnon_served_demand.csv
write_dualsbalance_duals.csv, co2_cap_duals.csv
write_full_timeseriesfull_time_series/
write_time_weightstime_weights.csv

Extracting Results as DataFrames

The following functions return output data as Julia DataFrame objects without writing to disk. They are useful for post-processing within a Julia session.

FunctionReturns
get_optimal_capacityOptimal total capacity per component
get_optimal_flowOptimal flow per edge per time step
get_optimal_storage_levelOptimal storage state of charge per time step
get_optimal_curtailmentCurtailment per VRE edge per time step
get_optimal_non_served_demandNon-served demand per node per time step

Filtering Results

write_capacity and write_flow (and their corresponding get_optimal_* functions) accept optional filters:

  • commodity: filter to one or more commodity types (e.g., commodity="Electricity")
  • asset_type: filter to one or more asset types (e.g., asset_type="ThermalPower")

Two pattern-matching modes are supported:

  1. Parameter-free matching"ThermalPower" matches ThermalPower{NaturalGas}, ThermalPower{Uranium}, etc.
  2. Wildcard matching"ThermalPower*" additionally matches ThermalPowerCCS{NaturalGas}, etc.
# Write only electricity flows for thermal power plants
write_flow("flows_elec_thermal.csv", system, commodity="Electricity", asset_type="ThermalPower")

See Also