Trade Model Setup - High-Level Overview

Purpose

The trade model optimizes global steel and iron trade flows by solving a linear programming (LP) problem. It determines the most cost-effective way to route materials from suppliers through production facilities to demand centers, subject to capacity constraints, trade policies, and physical limitations.

Core Concept

The model represents the global steel value chain as a network:

  • Nodes: Suppliers (mines), production facilities (furnaces), and demand centers (regions)

  • Edges: Valid material flows between compatible technologies

  • Objective: Minimize total cost (production + transport + tariffs + carbon)

  • Constraints: Capacity limits, trade policies, distance restrictions, feedstock ratios

Main Functions

1. set_up_steel_trade_lp() - Build the Optimization Model

What it does: Constructs the complete LP model structure from simulation data.

Process:

  1. Initializes an empty LP model with solver tolerance settings

  2. Adds all commodities being modeled (steel, iron, etc.)

  3. Creates process centers for suppliers, production facilities, and demand

  4. Defines valid connections between process types

  5. Applies optional constraints (tariffs, distance limits, feedstock ratios)

  6. Adds location-specific transportation costs if available

Key decisions:

  • Only includes active furnace groups (configurable status filter)

  • Scales production capacity by safety factor (typically 95%)

  • Reuses process definitions across multiple furnaces with same technology

Outputs: A fully configured TradeLPModel ready for optimization


2. Helper Functions - Building Model Components

create_process_from_furnace_group()

Purpose: Converts a furnace group’s technology specifications into an LP process definition.

What it captures:

  • Input-output relationships (bill of materials)

  • Minimum/maximum feedstock ratios

  • Secondary feedstock requirements

  • Energy costs per input type

Handles edge cases:

  • Skips feedstocks with missing or invalid data

  • Warns about technologies with no primary outputs

  • Reuses existing BOM elements when possible


add_furnace_groups_as_process_centers()

Purpose: Represents each steel production facility as an LP node.

What it models:

  • Production capacity (scaled by availability factor)

  • Geographic location for distance calculations

  • Production cost (carbon cost)

  • Soft minimum utilization target

Filters: Only includes furnaces with active operating status


add_demand_centers_as_process_centers()

Purpose: Represents regional steel demand as LP nodes.

What it models:

  • Regional demand quantity for the simulation year

  • Geographic center of demand region

  • Single shared demand process (all regions demand “steel”)


add_suppliers_as_process_centers()

Purpose: Represents raw material sources (mines, scrap yards) as LP nodes.

What it models:

  • Supply capacity for the simulation year

  • Geographic location

  • Production/extraction cost

  • One process type per commodity (e.g., all scrap sources “scrap_supply”)


3. Constraint Functions

enforce_trade_tariffs_on_allocations()

Purpose: Applies trade policy restrictions to cross-border flows.

Supports three tariff types:

  1. Volume quotas: Maximum tons per year on a route

  2. Absolute taxes: Fixed cost per ton ($/ton)

  3. Percentage taxes: Cost based on commodity price (% of market price)

Features:

  • Wildcard support for country groups (e.g., “any country to EU”)

  • Handles iron product families (hot metal, pig iron, DRI → “iron”)

  • Accumulates multiple taxes on same route


fix_to_zero_allocations_where_distance_doesnt_match_commodity()

Purpose: Enforces physical distance constraints on commodity transport.

Logic:

  • Hot metal: Can only travel short distances (~100km) due to cooling

  • Pig iron/steel: Made for long-distance transport

  • Fixes LP variables to zero for infeasible distance-commodity pairs

Applied before solving and reduces model size.


Secondary Feedstock & Aggregated Constraints

Purpose: Limits scrap availability and enforces technology-specific feedstock ratios.

Secondary feedstock constraints:

  • Regional limits on scrap, recycled materials

  • Example: “Europe can only source 50M tons scrap/year”

Aggregated constraints:

  • Technology-level min/max ratios

  • Example: “EAF must use 50-90% scrap, 10-50% DRI”


4. solve_steel_trade_lp_and_return_commodity_allocations() - Solve & Extract Results

What it does:

  1. Solves the LP optimization problem using Pyomo/HiGHS solver

  2. Extracts optimal allocation values from solver variables

  3. Maps LP results back to domain objects (plants, suppliers, demand centers)

  4. Filters out negligible allocations (< 0.0001 tons)

Error handling:

  • Returns empty allocations if solver fails to find optimal solution

  • Logs detailed error messages with termination condition

  • Continues simulation rather than crashing

Debug output:

  • Writes trade_lp_variables.csv with all allocation details

  • Logs statistics on non-zero allocations per commodity

Outputs: Dictionary mapping each commodity to its optimal allocation flows


5. Post-Processing Functions

identify_bottlenecks()

Purpose: Analyzes results to find capacity-constrained facilities.

What it detects:

  • Furnace groups operating at or near maximum capacity

  • Potential supply chain chokepoints

  • Useful for understanding why demand might not be fully met

Note: Currently logs warnings but doesn’t return structured data.


adapt_allocation_costs_for_carbon_border_mechanisms()

Purpose: Applies carbon border adjustment mechanisms (CBAM) to trade costs.

What it models:

  • Export rebates when high-carbon-price region exports to low-carbon-price region

  • Import adjustments when low-carbon-price region exports to high-carbon-price region

  • Prevents double-counting when countries belong to multiple policy regions

Generalized design: Works with any carbon border mechanism (EU CBAM, OECD, etc.), not just EU-specific.

Note: Called separately from main setup, typically in allocation workflow.


Configuration

Key SimulationConfig Parameters

Model behavior:

  • lp_epsilon: Solver tolerance (1e-3) - how close to constraints is acceptable

  • capacity_limit: Production safety factor (0.95) - models realistic availability

  • active_statuses: Which furnace states to include (e.g., [“operating”, “mothballed”])

Physical constraints:

  • hot_metal_radius: Maximum hot metal transport distance (~100km)

  • closely_allocated_products: Commodities limited to short distances

  • distantly_allocated_products: Commodities requiring long transport

Economic data:

  • primary_products: Which commodities to optimize ([“steel”, “iron”])

  • transport_kpis: Location-specific transport costs and emissions


Integration with Simulation

The trade model is called during each simulation time step:

  1. Allocation Model prepares input data (plants, demand, suppliers for current year)

  2. Setup phase builds LP model with set_up_steel_trade_lp()

  3. Optional adjustments apply carbon border mechanisms

  4. Solve phase optimizes with solve_steel_trade_lp_and_return_commodity_allocations()

  5. Analysis phase identifies bottlenecks and validates results

  6. Allocations are returned to simulation for plant-level profit calculations


For Detailed Implementation

For implementation details, parameter types, and code examples, see the comprehensive docstrings in each function within src/steelo/domain/trade_modelling/set_up_steel_trade_lp.py.