Downstream Emissions

Contents

Overview | Asset Structure | Flow Equations | Input File (Standard Format) | Types - Asset Structure | Constructors | Examples | Best Practices | Input File (Advanced Format)

Overview

Downstream emissions assets in Macro represent end-use commodity consumption processes at the downstream end of a value chain. They take in a commodity from the modeled system, pass that commodity to a demand or consuming node, and emit CO2 according to an emission_rate. These assets are defined using either JSON or CSV input files placed in the assets directory, typically named with descriptive identifiers like downstreamemissions.json or downstreamemissions.csv.

This asset is intended for cases where the commodity is routed to an external node that already exists in the system, including cases where several assets share the same downstream demand node. In other words, DownstreamEmissions adds emissions to a shared downstream node rather than owning a dedicated demand node internally.

The current implementation is generic over commodity type, so the same asset can represent downstream emissions from liquid fuels, natural gas, or other commodities supported by the model.

This distinction is important relative to the planned DownstreamUse asset: DownstreamEmissions routes flow to an external node via fuel_demand_end_vertex, whereas DownstreamUse is intended for cases where the asset itself will include a demand node.

For backward compatibility, DownstreamUse and FuelsEndUse remain available as aliases of DownstreamEmissions.

Asset Structure

A downstream emissions asset consists of four main components:

  1. Transformation Component: Balances commodity throughput and emissions
  2. Fuel Edge: Represents the incoming commodity flow from the modeled system
  3. Fuel Demand Edge: Represents the outgoing commodity flow to an external end-use or demand node
  4. CO2 Edge: Represents emitted CO2 sent to a sink or location

DownstreamEmissions does not create its own node. The outgoing fuel_demand_edge must connect to a node that is already defined elsewhere in the system.

Here is a graphical representation of the downstream emissions asset:

%%{init: {'theme': 'base', 'themeVariables': { 'background': '#D1EBDE' }}}%% flowchart LR subgraph "DownstreamEmissions" direction TB A{{..}} E((Commodity)) F((Commodity)) G((CO2)) E a@--fuel_edge--> A A b@--fuel_demand_edge--> F A c@--co2_edge--> G end style A fill:black,stroke:black,color:black; style E font-size:21px,r:55px,fill:#d3b683,stroke:black,color:black,stroke-dasharray: 3,5; style F font-size:21px,r:55px,fill:#d3b683,stroke:black,color:black,stroke-dasharray: 3,5; style G font-size:21px,r:55px,fill:#A9A9A9,stroke:black,color:black,stroke-dasharray: 3,5; linkStyle 0 stroke:#d3b683,stroke-width: 2px; a@{ animate: true }; linkStyle 1 stroke:#d3b683,stroke-width: 2px; b@{ animate: true }; linkStyle 2 stroke:#A9A9A9,stroke-width: 2px; c@{ animate: true };

Flow Equations

The downstream emissions asset follows these relationships:

\[\begin{aligned} \text{flow}_{fuel\_demand} &= \text{flow}_{fuel} \\ \text{flow}_{co2} &= \text{flow}_{fuel} \cdot \epsilon_{emission\_rate} \end{aligned}\]

Where:

Input File (Standard Format)

The easiest way to include a downstream emissions asset in a model is to create a new file (either JSON or CSV) and place it in the assets directory together with the other assets.

Because this asset does not contain its own demand node, the fuel_demand_end_vertex should point to an existing node in nodes.json or to another node created elsewhere in the case definition.

your_case/
├── assets/
│   ├── downstreamemissions.json    # or downstreamemissions.csv
│   ├── other_assets.json
│   └── ...
├── system/
├── settings/
└── ...

This file can either be created manually, or using the template_asset function, as shown in the Adding an Asset to a System section of the User Guide. The file will be automatically loaded when you run your Macro model.

The following is an example of a downstream emissions asset input file:

{
    "downstream_emissions": [
        {
            "type": "DownstreamEmissions",
            "instance_data": [
                {
                    "id": "liquid_fuels_use_SE",
                    "location": "SE",
                    "fuel_commodity": "LiquidFuels",
                    "fuel_demand_commodity": "LiquidFuels",
                    "fuel_demand_end_vertex": "liquid_fuels_demand_SE",
                    "emission_rate": 0.25,
                    "fuel_demand_investment_cost": 2500,
                    "fuel_demand_fixed_om_cost": 100,
                    "fuel_demand_variable_om_cost": 2.0,
                    "co2_sink": "co2_atm_SE"
                }
            ]
        }
    ]
}
Global Data vs Instance Data

When working with JSON input files, the global_data field can be used to group data that is common to all instances of the same asset type. This is useful for setting constraints that are common to all instances of the same asset type and avoid repeating the same data for each instance. See the Examples section below for an example.

The following tables outline the attributes that can be set for a downstream emissions asset.

Essential Attributes

FieldTypeDescription
typeStringAsset type identifier: "DownstreamEmissions"
idStringUnique identifier for the downstream emissions instance
locationStringGeographic location/node identifier

Conversion Process Parameters

FieldTypeDescriptionUnitsDefault
emission_rateFloat64CO2 emissions per unit of incoming commodity throughputcommodity-dependent0.0
fuel_commodityStringCommodity consumed by the fuel_edge-"LiquidFuels"
fuel_demand_commodityStringCommodity delivered by the fuel_demand_edge-"LiquidFuels"
fuel_demand_end_vertexStringEnd vertex for the outgoing demand edge-missing
co2_sinkStringEnd vertex for emitted CO2-missing
timedataStringTime series key used for the transformation and commodity edges-"LiquidFuels"

Simple-format edge attributes use edge-specific prefixes. For example, incoming commodity edge fields are written as fuel_investment_cost, fuel_existing_capacity, and fuel_constraints; outgoing demand edge fields use the fuel_demand_ prefix; and CO2 edge fields use the co2_ prefix.

Constraints Configuration

Downstream emissions assets can have different constraints applied to them, and the user can configure them using the following fields:

FieldTypeDescription
transform_constraintsDict{String,Bool}List of constraints applied to the transformation component.
fuel_constraintsDict{String,Bool}List of constraints applied to the incoming commodity edge.
fuel_demand_constraintsDict{String,Bool}List of constraints applied to the outgoing demand edge.
co2_constraintsDict{String,Bool}List of constraints applied to the CO2 edge.

Users can refer to the Adding Asset Constraints to a System section of the User Guide for a list of all the constraints that can be applied to a downstream emissions asset.

Default constraints

To simplify the input file and the asset configuration, the following constraints are applied to the downstream emissions asset by default:

Investment Parameters

FieldTypeDescriptionUnitsDefault
fuel_demand_can_retireBooleanWhether outgoing demand capacity can be retired-edge default
fuel_demand_can_expandBooleanWhether outgoing demand capacity can be expanded-edge default
fuel_demand_existing_capacityFloat64Initial installed outgoing demand capacityMW or commodity flow per timestepedge default
fuel_demand_capacity_sizeFloat64Unit size for capacity decisions-edge default

Additional Investment Parameters

If MaxCapacityConstraint or MinCapacityConstraint are added to the constraints dictionary for the outgoing demand edge, the following parameters are used by Macro:

FieldTypeDescriptionUnitsDefault
fuel_demand_max_capacityFloat64Maximum allowed outgoing demand capacityMW or commodity flow per timestepInf
fuel_demand_min_capacityFloat64Minimum allowed outgoing demand capacityMW or commodity flow per timestep0.0

Economic Parameters

FieldTypeDescriptionUnitsDefault
fuel_demand_investment_costFloat64CAPEX per unit outgoing demand capacity$/MW or $/commodity-flowedge default
fuel_demand_annualized_investment_costUnion{Nothing,Float64}Annualized CAPEX$/MW/yr or $/commodity-flow/yrcalculated
fuel_demand_fixed_om_costFloat64Fixed O&M costs for the outgoing demand edge$/MW/yredge default
fuel_demand_variable_om_costFloat64Variable O&M costs for the outgoing demand edge$/MWh or $/commodity unitedge default
fuel_demand_waccFloat64Weighted average cost of capitalfractionedge default
fuel_demand_lifetimeIntAsset lifetime in yearsyearsedge default
fuel_demand_capital_recovery_periodIntInvestment recovery periodyearsedge default
fuel_demand_retirement_periodIntRetirement periodyearsedge default

Operational Parameters

FieldTypeDescriptionUnitsDefault
fuel_demand_availabilityDictAvailability file path and header for the outgoing demand edge-Empty

Additional Operational Parameters

If MinFlowConstraint is added to the constraints dictionary for the outgoing demand edge, the following parameter is used:

FieldTypeDescriptionUnitsDefault
fuel_demand_min_flow_fractionFloat64Minimum outgoing demand flow as fraction of capacityfraction0.0

If RampingLimitConstraint is added to the constraints dictionary for the outgoing demand edge, the following parameters are used:

FieldTypeDescriptionUnitsDefault
fuel_demand_ramp_up_fractionFloat64Maximum increase in outgoing demand flow between timestepsfraction1.0
fuel_demand_ramp_down_fractionFloat64Maximum decrease in outgoing demand flow between timestepsfraction1.0

Types - Asset Structure

The DownstreamEmissions asset is defined as follows:

struct DownstreamEmissions{T} <: AbstractAsset
    id::AssetId
    fuelsenduse_transform::Transformation
    fuel_edge::Edge{<:T}
    fuel_demand_edge::Edge{<:T}
    co2_edge::Edge{<:CO2}
end

const DownstreamUse = DownstreamEmissions
const FuelsEndUse = DownstreamEmissions

Constructors

Default constructor

DownstreamEmissions(
    id::AssetId,
    fuelsenduse_transform::Transformation,
    fuel_edge::Edge{T},
    fuel_demand_edge::Edge{T},
    co2_edge::Edge{<:CO2}
) where T<:Commodity

Factory constructor

make(asset_type::Type{DownstreamEmissions}, data::AbstractDict{Symbol,Any}, system::System)
FieldTypeDescription
asset_typeType{DownstreamEmissions}Macro type of the asset
dataAbstractDict{Symbol,Any}Dictionary containing the input data for the asset
systemSystemSystem to which the asset belongs

Examples

This section contains examples of how to use the downstream emissions asset in a Macro model.

Multiple downstream emissions assets with shared defaults

This example shows how to create two downstream emissions assets in different zones with shared global data and zone-specific emission_rate and cost assumptions. Both assets route flow to an external demand node rather than owning separate internal demand nodes.

JSON Format:

{
    "downstream_emissions": [
        {
            "type": "DownstreamEmissions",
            "global_data": {
                "fuel_commodity": "NaturalGas",
                "fuel_demand_commodity": "NaturalGas",
                "fuel_demand_end_vertex": "natgas_demand",
                "fuel_demand_variable_om_cost": 1.0,
                "co2_sink": "co2_atm"
            },
            "instance_data": [
                {
                    "id": "natgas_use_SE",
                    "location": "SE",
                    "emission_rate": 0.18,
                    "fuel_demand_investment_cost": 1200,
                    "fuel_demand_fixed_om_cost": 80
                },
                {
                    "id": "natgas_use_NE",
                    "location": "NE",
                    "emission_rate": 0.16,
                    "fuel_demand_investment_cost": 1500,
                    "fuel_demand_fixed_om_cost": 95
                }
            ]
        }
    ]
}

CSV Format:

Typeidlocationfuel_commodityfueldemandcommodityfueldemandend_vertexemission_ratefueldemandinvestment_costfueldemandfixedomcostfueldemandvariableomcostco2_sink
DownstreamEmissionsnatgasuseSESENaturalGasNaturalGasnatgas_demand0.181200801.0co2_atm
DownstreamEmissionsnatgasuseNENENaturalGasNaturalGasnatgas_demand0.161500951.0co2_atm

Best Practices

  1. Use explicit commodity names for both fuel_commodity and fuel_demand_commodity, even when they are the same.
  2. Set fuel_demand_end_vertex explicitly so the outgoing demand flow is routed to the intended external node.
  3. Use this asset when several emitting processes should connect to the same shared downstream node.
  4. Set co2_sink explicitly when emissions should be routed to a dedicated CO2 node rather than the asset location.
  5. Keep emission_rate units consistent with the commodity flow units used in the rest of the model.
  6. Use global_data for shared cost and commodity settings when creating many downstream emissions assets.

Input File (Advanced Format)

Macro provides an advanced format for defining downstream emissions assets, offering users and modelers detailed control over transformation and edge specifications.

To understand the advanced format, consider the graph representation and the type definition of a downstream emissions asset. The input file mirrors this hierarchical structure.

A downstream emissions asset in Macro is composed of a Transformation object and three Edge objects. The input file for a downstream emissions asset is therefore organized as follows:

{
    "transforms": {
        // ... transformation-specific attributes ...
    },
    "edges": {
        "fuel_edge": {
            // ... incoming commodity edge-specific attributes ...
        },
        "fuel_demand_edge": {
            // ... outgoing demand edge-specific attributes ...
        },
        "co2_edge": {
            // ... CO2 edge-specific attributes ...
        }
    }
}

Below is an example of an advanced input file for a downstream emissions asset:

{
    "downstream_emissions": [
        {
            "type": "DownstreamEmissions",
            "instance_data": [
                {
                    "id": "liquid_fuels_use_SE",
                    "location": "SE",
                    "transforms": {
                        "timedata": "LiquidFuels",
                        "emission_rate": 0.25,
                        "constraints": {
                            "BalanceConstraint": true
                        }
                    },
                    "edges": {
                        "fuel_edge": {
                            "commodity": "LiquidFuels",
                            "start_vertex": "liquid_fuels_SE"
                        },
                        "fuel_demand_edge": {
                            "commodity": "LiquidFuels",
                            "end_vertex": "liquid_fuels_demand_SE",
                            "investment_cost": 2500,
                            "fixed_om_cost": 100,
                            "variable_om_cost": 2.0
                        },
                        "co2_edge": {
                            "commodity": "CO2",
                            "end_vertex": "co2_atm_SE"
                        }
                    }
                }
            ]
        }
    ]
}

Key Points

  • The transforms block configures the internal transformation object, including timedata, constraints, and emission_rate.
  • The fuel_edge and fuel_demand_edge can be assigned any supported commodity type, allowing the asset to model downstream emissions for multiple sectors.
  • The co2_edge always uses the CO2 commodity and can terminate either at co2_sink or at the asset location.
  • For a comprehensive list of attributes that can be configured for edges and transformations, refer to the edges and transformations pages of the Macro manual.