CIMS – macroABM Linkage

The CIMS–macroABM linkage couples CIMS (a detailed energy-technology model) with macroabm-ca (an agent-based macroeconomic model of the Canadian economy). It lets energy-technology transitions feed into macroeconomic dynamics and lets the resulting economic activity feed back into CIMS as a new demand/growth trajectory.

It lives side-by-side with the CIMS–COPPER–SILVER linkage in this repo and runs completely independently: it has its own orchestrator (linkage_macroabm.py), its own runner scripts (scripts/*macro*), and its own scenario folders. Running one workflow never touches the other.

This is the ITERATIVE linkage. There is also a one-way CIMS-COPPER → macroABM linkage, which takes a finished CIMS-COPPER scenario as fixed input (you stage the two models' output files; it never launches them), adds COPPER's electricity supply explicitly, and carries a larger set of energy channels — quantity anchors, capacity floor/ceiling/gate and price pinning as well as intensity targets. It costs one macroABM run instead of a CIMS+macroABM run per iteration, and it is the right default for scenario analysis.

Use this iterative loop when the question is specifically whether the economy would sustain the energy pathway, so the economic response must feed back and re-solve. See the side-by-side comparison.


How the linkage works

The linkage is an iterative outer loop:

  1. CIMS runs and produces, among other things, energy demand by fuel & sector and technology investment.
  2. A macroABM preprocessing step reads CIMS' standard result files and translates them (energy demand + investment by sector & fuel) into the matrices the macroABM consumes.
  3. The provincial macroABM runs, using those matrices to override how efficiently each sector uses energy and capital (firms.link()), so it leverages CIMS' engineering detail.
  4. The macroABM produces production by sector over time for each province.
  5. That production is written back into CIMS as a service-request growth trajectory (the macroabm_production policy overlay).
  6. CIMS runs again with the new activity trajectory.
  7. The loop repeats until per-period national GDP growth changes by less than the configured tolerance between iterations (default 10%; set Convergence.mode = "provincial" for the legacy all-provinces rule).

Optionally, adding "LabourABM" to models_to_run appends a one-way LabourABM stage that runs once after the loop converges: it turns the converged macroABM production into occupation-level labour-market outcomes (employment/unemployment by region × occupation). See the Setup Guide and Quick-start.

┌──────────────────────────────────────────────────────────────────┐
│  Outer loop  (linkage_macroabm.py)                                 │
│                                                                    │
│  1. CIMS runs                 → standard results CSVs              │
│  2. Extract (macro_data)      → requested_quantities + investment  │
│  3. Provincial macroABM runs  → firms.link() at CIMS years         │
│  4. get_production_annual()   → production by sector & province    │
│  5. Write growth-ratio policy → macroabm_production_<REG>.csv      │
│  6. CIMS re-runs with policy                                       │
│  7. Converged? national GDP growth Δ < tolerance → stop, else iterate │
└──────────────────────────────────────────────────────────────────┘

Where each piece lives

A core design goal is that CIMS requires no source-code changes — it only ever reads/writes standard files.

Responsibility Location
Extract CIMS results → macroABM inputs (preprocessing) macroabm-ca → macro_data/processing/macroabm_cims_data_processing/cims_results_extractor.py
Editable CIMS↔macroABM sector & region mapping macroabm-ca → .../macroabm_cims_data_processing/data/*.csv
Core linkage logic (firms.link, get_production_annual) macroabm-ca → macromodel/agents/firms/firms.py
macroABM → CIMS feedback (postprocessing, growth-ratio) macroabm-ca → .../macroabm_cims_data_processing/cims_production_writer.py
Provincial linkage driver macroabm-ca → scenarios/run_cims_linkage.py
Orchestration / runner M3-linkages → linkage_macroabm.py + scripts/*macro*
CIMS warm-restart (optional) M3-linkages → scripts/cims_warm_restart.py (history checkpoint + partial re-solve)
LabourABM stage (optional) M3-linkages → scripts/labourabm_runner.py, driving labourabm → scripts/{1_format_production_data,2_run_bridge,3_run_abm_macromodel}.py

When warm_start = true in the scenario config, CIMS solves the pre-2025 history once, checkpoints it, and re-solves only future milestone years each iteration — cutting per-iteration CIMS runtime without changing results. See Configuration Reference.


Supported repositories & branches

Model / Tool Repository Branch used by runner
CIMS model runner https://gitlab.com/sesit/cims-models-fork main
macroABM model https://github.com/uvic-sesit/macroabm-ca cims-macro-linkage
LabourABM model (optional stage) https://gitlab.com/sesit/macrocosm/labourabm/model cims-macro-labour-branch
Linkage runner https://gitlab.com/sesit/M3-linkages cims-macro-linkage

Editable sector mapping (no more hard-coded classifications)

Historically the CIMS↔macroABM correspondence was hard-coded inside CIMS, so changing the classification meant editing CIMS source code, and a bad entry crashed the run. In this linkage the mapping lives in two plain CSV files you can edit freely (unmapped/misspelled entries are skipped with a warning, never a crash):

  • macroabm-ca/macro_data/processing/macroabm_cims_data_processing/data/cims_macro_sector_map.csv
  • macroabm-ca/macro_data/processing/macroabm_cims_data_processing/data/cims_macro_region_map.csv

See the Configuration Reference for the column meanings.


⚠️ CIMS logging-template note (read this if you pull a new CIMS)

To reconstruct investment and stock from CIMS' standard output (instead of editing CIMS code), the linkage needs CIMS to log new_stock and total_stock at the technology level. The runner does this automatically by appending those two lines to cims-models-fork/results/results_tech.txt (a data file, not code) if they are missing.

If you pull a fresh CIMS checkout that overwrites results_tech.txt, the runner re-applies the change on the next run — but if you ever see empty investment in the extracted matrices, this template is the first thing to check.