NATM stands for NavAero Transition Model.
NATM is a technology transition diffusion model for aviation and maritime transport systems. It is designed to simulate how operators adopt new aircraft, vessels, fuels, and related technologies over time under changing policy, cost, infrastructure, and operational conditions.
The model is built as a Mesa-based agent-based simulation with explicit agents, case data, decision-logic plugins, fleet management, environment state, and structured outputs. The goal is to provide a cleaner and more maintainable architecture than the earlier Melodie-based implementation, while still capturing the business and policy dynamics behind technology diffusion.
In practical terms, NATM is intended to help explore questions such as:
- how quickly alternative technologies diffuse across operators
- how policy and fuel prices affect investment decisions
- how much fuel demand shifts by energy carrier over time
- how emissions and investment costs evolve during the transition
The current repository includes working aviation-passenger, aviation-cargo, maritime-cargo, and maritime-passenger test cases, while the architecture is designed to extend further into additional transport applications as the model grows.
- Mesa-based agent-based simulation for aviation and maritime transition pathways
- Aviation passenger, aviation cargo, maritime cargo, and maritime passenger cases
- Flexible operator decision logic selected through case input data
- Optional ambiguity-aware investment logic over multiple future scenarios
- Demand-driven aviation growth using passenger-km and tonne-km planning inputs
- Optional OpenSky/OpenAP preprocessing for aviation activity, fuel, and emissions
- Structured CSV and SQLite outputs for analysis and dashboards
- Solara dashboards for live cases, saved runs, preprocessing outputs, and route maps
- Architecture
- Aviation preprocessing guide
- Dashboard guide
- Aviation passenger input reference
- Aviation cargo input reference
- Maritime cargo input reference
- Maritime passenger input reference
NATM requires Python 3.11 or newer.
git clone https://github.com/Manish-Khanra/NATM.git
cd NATM
python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e .[dev]If your default python does not point to Python 3.11+, use a specific
interpreter such as:
py -3.11 -m venv .venv.venv\Scripts\Activate.ps1
python run.pyThat launcher writes the results automatically into:
simulation_results/<selected_example>/
including model_summary.csv, the detailed CSV tables, and natm_runs.sqlite.
If you want to run a case directly through the CLI instead:
natm --case baseline-passenger-transition --output simulation_results/baseline.csvTo export the richer Mesa result tables as well:
natm --case baseline-passenger-transition --output simulation_results/baseline.csv --details-dir simulation_results/baseline-detailsTo persist both case inputs and run outputs into SQLite:
natm --case baseline-passenger-transition --output simulation_results/baseline.csv --details-dir simulation_results/baseline-details --sqlite-db simulation_results/natm_runs.sqliteInstall the hooks once per clone:
.venv\Scripts\Activate.ps1
pre-commit installRun them manually across the whole repository:
pre-commit run --all-filesNATM now also includes a dedicated aviation data-ingestion and preprocessing layer for building data-grounded baseline aviation inputs from:
- fleet stock tables
- OpenSky aircraft metadata
- OpenSky / Zenodo monthly flight lists
- airport metadata
- Germany calibration targets
The preprocessing code is separate from the simulation core and lives in:
navaero_transition_model/aviation_preprocessing/
Typical processed outputs are written to:
data/processed/aviation/
You can run the preprocessing CLI with a synthetic example like this:
.venv\Scripts\Activate.ps1
natm-aviation-preprocess `
--stock-input data\baseline-passenger-transition\aviation_fleet_stock.csv `
--opensky-raw data\examples\aviation_preprocessing\opensky_aircraft_db_sample.csv `
--flightlist-folder data\examples\aviation_preprocessing\opensky_flightlists `
--airport-metadata data\examples\aviation_preprocessing\airports_sample.csv `
--technology-catalog data\baseline-passenger-transition\aviation_technology_catalog.csv `
--calibration-input data\examples\aviation_preprocessing\germany_calibration_input.csvOpenAP fuel and emissions estimation is optional because it adds an extra flight-performance dependency. Install it only when you want to turn OpenSky/Zenodo flight lists into baseline fuel and emissions intensities:
python -m pip install -e .[openap]Then add the OpenAP flag to the preprocessing command:
natm-aviation-preprocess `
--stock-input data\baseline-passenger-transition\aviation_fleet_stock.csv `
--opensky-raw data\examples\aviation_preprocessing\opensky_aircraft_db_sample.csv `
--flightlist-folder data\examples\aviation_preprocessing\opensky_flightlists `
--airport-metadata data\examples\aviation_preprocessing\airports_sample.csv `
--technology-catalog data\baseline-passenger-transition\aviation_technology_catalog.csv `
--calibration-input data\examples\aviation_preprocessing\germany_calibration_input.csv `
--estimate-openap-fuel `
--openap-mode syntheticThis writes OpenAP flight, aircraft-type, route, mapping-log, and validation
outputs into data/processed/aviation/ and enriches
aviation_activity_profiles.csv for the core Mesa simulation.
You can also run the scenario-defined preprocessing flow from run.py. The
baseline passenger case stores its preprocessing recipe in
data/baseline-passenger-transition/scenario.yaml:
python run.py --mode aviation_preprocessing --example small_with_aviation_passengerThe same launcher can override the scenario OpenAP setting if needed:
python run.py `
--mode aviation_preprocessing `
--example small_with_aviation_passenger `
--estimate-openap-fuel `
--openap-mode syntheticOr in VS Code by editing the small config block in run.py:
selected_mode = "aviation_preprocessing"
selected_example = "small_with_aviation_passenger"The bridge file into the existing aviation model is:
data/<case-name>/aviation_activity_profiles.csv
If present in a case folder, NATM merges it onto the aviation fleet stock baseline during case loading.
For the full preprocessing workflow, outputs, and architecture notes, see:
docs/aviation-preprocessing-guide.md
If you want to use the NATM Solara/Mesa dashboards, install the optional dashboard dependencies:
.venv\Scripts\Activate.ps1
python -m pip install -e .[dashboard]Then you can launch the standard live/saved-results dashboard:
solara run dashboard_examples/common_case_dashboard.pyThe standalone cartographic dashboard opens a browser-native deck.gl map for aviation result folders:
solara run dashboard_examples/cartographic_dashboard.pyEach dashboard supports two modes inside the browser:
Live caseSaved results
Live case reruns the configured case directly from data/<case-name>/.
Saved results reads an already generated folder under:
simulation_results/<your-run-name>/
In the dashboard UI:
- open the
Dashboard Sourcecard - choose
Saved results - select the results folder from the dropdown
The saved-results dropdown only shows folders that contain the expected CSV outputs for that application.
The cartographic dashboard reads simulation_results/<your-run-name>/
directly. When postprocessed airport_fuel_demand.csv and
route_energy_flow.csv files exist, it uses those map-ready airport and route
layers. Otherwise, it uses aircraft.csv for simulated years and airport
demand, and falls back to processed aviation route geometry when route-level map
outputs are not present.
To create dashboard-ready airport fuel-demand and route-flow files after a run:
natm-airport-fuel-allocation --results simulation_results/<your-run-name>If the new command is not recognized before reinstalling the editable package, use:
python -m navaero_transition_model.postprocessing.airport_fuel_allocation_cli --results simulation_results/<your-run-name>This postprocessor is separate from the investment/adoption simulation. It uses flightlist/OpenAP sequences when aircraft identifiers match; otherwise it falls back to synthetic allocation from simulated aircraft energy and processed route shares.
Dashboard notes:
- the normal dashboards now include an
Emissionspanel that can show all detected pollutant columns, including OpenAPco2_kg,h2o_kg,nox_kg,co_kg,hc_kg,soot_kg, andsox_kg - pollutant totals are displayed in tonnes
- the cartographic map tooltips include metric labels and units
- the cartographic metric buttons use readable names, with a display-unit toggle for convertible metrics such as fuel uplift mass
- cartographic MWh metrics switch to TWh at
1,000 MWh - cartographic fuel uplift mass and pollutant metrics switch from kg to tonnes for large displayed values
If you already installed the dashboard stack and see a Starlette.__init__()
error mentioning on_startup, repair the environment with:
python -m pip install "starlette<1" "solara-server[starlette]>=1.40"For the full dashboard workflow, see:
docs/dashboard-guide.md
pytest.venv\Scripts\Activate.ps1
pre-commit run --all-files
pytest
python run.pyThe default run.py launcher writes outputs to:
simulation_results/<selected_example>/
This folder contains:
model_summary.csvagents.csvaircraft.csvaviation_technology.csvaviation_energy_emissions.csvaviation_investments.csvmaritime_technology.csvmaritime_energy_emissions.csvmaritime_investments.csvaviation_robust_frontier.csvmaritime_robust_frontier.csvnatm_runs.sqlite
Named example presets currently included in run.py:
small_with_aviation_passengersmall_with_aviation_cargosmall_with_maritime_cargosmall_with_maritime_passenger
navaero_transition_model/core/scenario.py: scenario schema and YAML loadernavaero_transition_model/aviation_preprocessing/: aviation ingestion, enrichment, activity profiling, allocation, calibration, and baseline-building workflownavaero_transition_model/core/policy.py: plain Python policy/config objects and yearly policy signalsnavaero_transition_model/core/loaders/: loader classes and convenience functions for case ingestionnavaero_transition_model/core/agent_types/: parent and specialized Mesa agent classesnavaero_transition_model/core/case_inputs/: case input objects for fleet stock, technology catalog, and scenario tablesnavaero_transition_model/core/decision_logic/: pluggable investment/adoption logic implementationsnavaero_transition_model/core/fleet_management/: fleet state and fleet-management objectsnavaero_transition_model/core/environment.py: shared country-and-corridor world layernavaero_transition_model/core/model.py: MesaModel, AgentSet activation, and DataCollector outputnavaero_transition_model/core/database/: optional SQLite-backed database writing for case inputs and run outputsnavaero_transition_model/core/result_exports/: exporter classes for detailed simulation result tablesnavaero_transition_model/cli.py: command-line entry pointdashboard_examples/: small Solara/Mesa dashboard examplesdocs/dashboard-guide.md: how to launch dashboards and switch between live and saved-results modedocs/aviation-preprocessing-guide.md: aviation preprocessing architecture, outputs, and CLI usagedocs/architecture.md: detailed system architecture and runtime flowdocs/aviation-passenger-reference.md: passenger-specific reference foraviation_scenario.csvdocs/aviation-cargo-scenario-reference.md: cargo-specific reference foraviation_scenario.csvin cargo aviation casesdocs/maritime-cargo-reference.md: cargo-specific reference formaritime_scenario.csvdocs/maritime-passenger-reference.md: passenger-specific reference formaritime_scenario.csvdata/<case-name>/scenario.yaml: case configurationdata/<case-name>/*.csv: input data for that case
The baseline-passenger-transition case includes the passenger-specific 3-file input
structure:
aviation_fleet_stock.csvaviation_technology_catalog.csvaviation_scenario.csv
The baseline-cargo-transition case uses the same aviation CSV filenames:
aviation_fleet_stock.csvaviation_technology_catalog.csvaviation_scenario.csv
The risk-attitudes-comparison case is a synthetic aviation
passenger example with three German airlines, one aircraft each, and one
decision_attitude per airline: risk_neutral, risk_averse, and
ambiguity_averse. It is intended for comparing ambiguity-aware robust
frontier outputs through 2040.
In technology catalogs, technology_name is the unique lookup key. For real
aviation datasets this can be a specific aircraft model such as A320neo,
A321XLR, or B787-9. segment is still used for demand, market-share,
planned-delivery, activity, and reporting scopes, but it is not part of the
technology identity. The example technology catalogs still include a segment
column as optional operating-context metadata, but the model no longer relies
on technology_name + segment as a composite key.
The baseline-maritime-cargo-transition case uses maritime-sector CSV filenames:
maritime_fleet_stock.csvmaritime_technology_catalog.csvmaritime_scenario.csv
The baseline-maritime-passenger-transition case uses the same maritime CSV
filenames:
maritime_fleet_stock.csvmaritime_technology_catalog.csvmaritime_scenario.csv
The fleet stock input can also carry an investment_logic column so each
operator agent can select its decision method by name. Legacy behavior is
available for every sector through legacy_weighted_utility. Older
sector-specific legacy names are still accepted as aliases for existing cases.
The ambiguity-aware extension also uses one strategy name for every sector:
ambiguity_aware_utility. Older sector-specific ambiguity-aware names are
still accepted as aliases for existing cases.
Fleet stock can optionally include decision_attitude with
risk_neutral, risk_averse, or ambiguity_averse. If it is missing, NATM
defaults to risk_neutral. The column only changes behavior for the
ambiguity-aware logic; legacy weighted-utility decisions are unchanged.
Scenario CSVs can optionally include scenario_id. If the column is missing,
all rows are treated as baseline. When present, the ambiguity-aware logic
evaluates candidate technologies over configured future scenarios while keeping
the existing blank-scope and specificity matching rules.
This is an ambiguity-aware extension of the existing utility-based fleet diffusion model. The model still simulates technology diffusion through fleet replacement and growth, but candidate technologies can now be evaluated over a set of possible future scenarios. Risk-neutral actors maximise expected utility, risk-averse actors use probability-weighted mean utility over the worst alpha probability mass, and ambiguity-averse actors use worst-case expected shortfall over a bounded probability-ambiguity set.
For copy-paste fleet-stock, scenario.yaml, and scenario_id examples, see
the investment logic guide.
For the passenger scenario CSV contract, see
docs/aviation-passenger-reference.md.
For a cargo-only view of the same contract, see
docs/aviation-cargo-scenario-reference.md.
For the maritime-passenger scenario CSV contract, see
docs/maritime-passenger-reference.md.
For the maritime-cargo scenario CSV contract, see
docs/maritime-cargo-reference.md.
For the system-level architecture, see docs/architecture.md.
For the dashboard workflow, see docs/dashboard-guide.md.
- Carbon-price ramp shared across sectors
- Sector-specific clean-fuel subsidies and adoption mandates
- Infrastructure buildout and learning effects
- Yearly transition pressure and effective cost outputs
- Mesa-native activation through
model.agents_by_type[...] .shuffle_do("step") - Mesa-native model and agent reporting through
mesa.DataCollector - Multiple operator agents per sector with heterogeneous fleet sizes and costs
- Aviation fleet-stock CSV aggregation into airline-specific Mesa agents
- Flexible agent decision logic chosen by
investment_logicfrom the input data - Agent inheritance structure with reusable parent classes for future agent types
- Object-oriented case data, technology catalog, scenario table, fleet, and output exporters
- A shared environment layer with country states and route/corridor effects
- Detailed aviation passenger, aviation cargo, maritime cargo, and maritime passenger outputs for stock, technology diffusion, energy/emissions, and investment activity
If you use NATM in your research, policy analysis, consulting, or engineering work, please cite the following paper:
- Manish Khanra, Shashank Deepak Prabhu, Martin Wietschel, Estimating energy demand for decarbonising the aviation and maritime fleets of Germany: An agent-based technology diffusion approach considering investment behaviour, published in Energy Nexus, Volume 20, 2025, Article 100557.
Please use the following BibTeX to cite the work:
@article{khanra2025estimating,
title = {Estimating energy demand for decarbonising the aviation and maritime fleets of Germany: An agent-based technology diffusion approach considering investment behaviour},
author = {Khanra, Manish and Prabhu, Shashank Deepak and Wietschel, Martin},
journal = {Energy Nexus},
volume = {20},
pages = {100557},
year = {2025},
issn = {2772-4271},
doi = {10.1016/j.nexus.2025.100557},
url = {https://www.sciencedirect.com/science/article/pii/S2772427125001974},
keywords = {Hard-to-abate sector, Agent-based model, Technology diffusion, Demand analysis, Aviation, Maritime}
}For citing a specific software version of NATM, use the repository citation
metadata in CITATION.cff.
NATM is licensed under the GNU General Public License, version 3 only
(GPL-3.0-only). See LICENSE for the full license text.
Copyright (C) 2026 Manish Gaebelein-Khanra.
Third-party software dependencies, datasets, and external data sources retain their own licenses, citation requirements, and terms of use.