-
Notifications
You must be signed in to change notification settings - Fork 58
Add tools.impacts: GMT-to-impact prediction toolkit via RIME emulators #479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Wegatriespython
wants to merge
19
commits into
iiasa:main
Choose a base branch
from
Wegatriespython:feat/physical-climate-impacts
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
be1d8ce
Add tools/impacts and tools/iamc helpers
Wegatriespython f783595
Add buildings physical-impact module
Wegatriespython 91215ad
Add wet + dry cooling physical-impact module
Wegatriespython f320ed4
Add water CID transforms and basin geometry helpers
Wegatriespython f7d4a8b
Add SPARRCLE project package and Workflow
Wegatriespython ad6364b
Add SSP1 buildings calibration files
Wegatriespython 7b3ca4b
Fix SPARRCLE MAGICC config paths
Wegatriespython f360574
Rationalize PR 479 test suite
Wegatriespython 23ceb67
Add netCDF4 to test dependencies
Wegatriespython 50b4a72
Require explicit building reference scenario
Wegatriespython 039ac74
Parameterize cooling region prefix
Wegatriespython f74cb76
Rename SPARCCLE project module and thread regions
Wegatriespython 61a62d4
Document SPARCCLE impact workflow
Wegatriespython bc936e1
Trim impact helper test prose
Wegatriespython 89dad82
Document physical impact application layers
Wegatriespython ee2fcbb
Clarify physical impact documentation boundaries
Wegatriespython dcf50e2
Move impact theory into documentation
Wegatriespython 0cb1574
Reformat empty CID fixture to satisfy ruff line length
Wegatriespython 0fc75ae
Add doc on theta coverage
Wegatriespython File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| .. currentmodule:: message_ix_models.tools.impacts | ||
|
|
||
| Climate impact prediction toolkit (:mod:`.tools.impacts`) | ||
| ********************************************************** | ||
|
|
||
| .. contents:: | ||
| :local: | ||
|
|
||
| Overview | ||
| ======== | ||
|
|
||
| :mod:`.tools.impacts` provides GMT-to-impact prediction via RIME regional | ||
| emulators, with helpers for assembling GMT ensembles from MAGICC output and | ||
| resampling sparse calibration inputs onto MESSAGE model years. | ||
|
|
||
| The toolkit is domain-agnostic: it predicts at native emulator resolution and | ||
| returns NumPy arrays. Domain modules under :mod:`.model.buildings`, | ||
| :mod:`.model.water.data`, and :mod:`.project.sparccle` own the transformation | ||
| to MESSAGE-compatible parameters. | ||
|
|
||
| RIME prediction is an adapted reimplementation of the GWL-binned | ||
| nearest-neighbor lookup from Byers et al. (2025), *Environ. Res.: Climate* | ||
| **4** 035011, `doi:10.1088/2752-5295/adee3d | ||
| <https://doi.org/10.1088/2752-5295/adee3d>`_; | ||
| upstream code at `iiasa/rime <https://github.com/iiasa/rime>`_ (GPL-3.0). | ||
| See :mod:`.tools.impacts.rime` for full attribution. | ||
|
|
||
| Usage | ||
| ===== | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| import numpy as np | ||
|
|
||
| from message_ix_models.tools.impacts import ( | ||
| GmtArray, | ||
| gmt_ensemble, | ||
| gmt_expectation, | ||
| load_magicc_gmt, | ||
| predict_rime, | ||
| ) | ||
|
|
||
| # Read a MAGICC climate-assessment Excel run-ensemble | ||
| gmt = load_magicc_gmt("/path/to/magicc_output_dir", n_runs=600) | ||
| # gmt.values: (n_runs, n_years); gmt.years: (n_years,) | ||
|
|
||
| # Single-trajectory prediction (ensemble-mean GMT) | ||
| mean = gmt_expectation(gmt) # values shape (n_years,) | ||
| qtot_1d = predict_rime( | ||
| mean.values, | ||
| "rime_regionarray_qtot_mean_CWatM_annual_window11.nc", | ||
| "qtot_mean", | ||
| ) # (157, n_years) | ||
|
|
||
| # Ensemble prediction with mean reduction | ||
| qtot_2d = predict_rime( | ||
| gmt.values, | ||
| "rime_regionarray_qtot_mean_CWatM_annual_window11.nc", | ||
| "qtot_mean", | ||
| aggregate="mean", | ||
| ) # (157, n_years) | ||
|
|
||
| RIME emulators (:mod:`.tools.impacts.rime`) | ||
| =========================================== | ||
|
|
||
| RIME datasets use GWL-binned nearest-neighbor lookup. Each emulator covers a | ||
| GMT range of 0.6–7.4 °C (ISIMIP3b-derived). Values outside this range return | ||
| NaN; values below the minimum are clipped with skewed Beta(2, 5) noise via | ||
| :func:`.clip_gmt`. | ||
|
|
||
| For ensemble input ``(n_runs, n_years)``, :func:`.predict_rime` returns a | ||
| Monte Carlo estimate of ``E_{P(GMT)}[f(GMT)]`` when called with | ||
| ``aggregate="mean"``. This is meaningful only when the emulator response is | ||
| approximately linear over the GMT range present in the ensemble; for | ||
| single-run input on a non-linear emulator it raises. Use | ||
| :func:`.check_emulator_linearity` to probe a dataset before relying on | ||
| ensemble means. :func:`.open_rime_dataset` opens a packaged NetCDF by | ||
| filename and caches the result. | ||
|
|
||
| Climate inputs (:mod:`.tools.impacts.climate`) | ||
| =============================================== | ||
|
|
||
| :func:`.load_magicc_gmt` reads a ``*_IAMC_climateassessment.xlsx`` file and | ||
| returns a :class:`.GmtArray` of per-run GSAT trajectories. | ||
| :func:`.gmt_ensemble` builds a :class:`.GmtArray` from any wide DataFrame with | ||
| year columns. :func:`.gmt_expectation` reduces an ensemble to its per-year | ||
| ``nanmean``. :func:`.persist_gmt_mean` writes the ensemble-mean trajectory | ||
| onto a scenario as a ``Physical Climate Impact|Surface Temperature (GSAT)`` | ||
| timeseries. | ||
|
|
||
| Temporal resampling (:mod:`.tools.impacts.temporal`) | ||
| ===================================================== | ||
|
|
||
| :func:`.sample_to_model_years` maps annual or sparse calibration inputs to | ||
| MESSAGE model years via ``method="point"`` (lookup), ``"average"`` (period | ||
| mean), or ``"interpolate"`` (linear infill between sparse anchors with | ||
| forward-fill beyond the last input). | ||
|
|
||
| Code reference | ||
| ============== | ||
|
|
||
| .. currentmodule:: message_ix_models.tools | ||
|
|
||
| .. autosummary:: | ||
| :toctree: _autosummary | ||
| :template: autosummary-module.rst | ||
| :recursive: | ||
|
|
||
| impacts |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| Physical impacts | ||
| **************** | ||
|
|
||
| .. contents:: | ||
| :local: | ||
|
|
||
| Architecture | ||
| ============ | ||
|
|
||
| Physical-impact support is split across three layers. Generic prediction | ||
| utilities live in :mod:`message_ix_models.tools.impacts`. They evaluate | ||
| packaged RIME emulators and return impact arrays at the emulator's native | ||
| resolution. The current file reader ingests MAGICC ensembles in the | ||
| ``climate-assessment`` workbook format; the downstream prediction utilities | ||
| only require an ensemble realization of global mean temperature and can be | ||
| fed by other simple climate models through :class:`~message_ix_models.tools.impacts.GmtArray`. | ||
|
|
||
| Domain application modules translate those predictions into MESSAGE scenario | ||
| edits. The current application modules are | ||
| :mod:`message_ix_models.model.buildings.impacts` for buildings demand and | ||
| :mod:`message_ix_models.model.water.data.cooling_impacts` for thermoelectric | ||
| cooling. Basin-level water transformations live in | ||
| :mod:`message_ix_models.model.water.data.impacts`. | ||
|
|
||
| Project workflows, such as :mod:`message_ix_models.project.sparccle`, choose | ||
| starter scenarios, input files, variants, and clone names. They do not define | ||
| the domain-specific MESSAGE parameters used for an impact. | ||
|
|
||
| Buildings | ||
| ========= | ||
|
|
||
| Buildings impacts replace the climate-sensitive part of aggregate | ||
| ``rc_spec`` and ``rc_therm`` demand. The replacement demand is calibrated in | ||
| three layers. | ||
|
|
||
| The correction-coefficient files contain archetype-level ``gamma`` terms. | ||
| STURM encodes stock turnover, access, cooling-area, and other internal | ||
| dynamics. RIME/CHILLED provides climate-responsive energy intensity. Energy | ||
| intensity multiplied by floor area does not by itself reproduce the STURM | ||
| time series, so ``gamma`` is constructed so the reference-temperature product | ||
| matches STURM baseline energy demand: | ||
|
|
||
| .. math:: | ||
|
|
||
| \mathrm{raw}_{r,a,t} = | ||
| \gamma_{r,a,t} \cdot EI_{r,a}(GSAT_t) \cdot F_{r,a,t} | ||
|
|
||
| where ``F`` is STURM floor area. In the packaged CSV files, ``gamma`` is the | ||
| ``correction_coeff`` column. | ||
|
|
||
| The ``theta`` files are a second calibration layer. The raw STURM trajectory | ||
| is not the same object as the calibrated residential/commercial demand that | ||
| enters MESSAGE. For each SSP, ``theta`` scales the node-year aggregate so the | ||
|
Wegatriespython marked this conversation as resolved.
|
||
| reference-GWL result matches the calibrated buildings heating and cooling | ||
| demand from the Shared Socioeconomic Pathways 2023 / WP-RC demand workflow. | ||
|
|
||
| The ``rc_sector_fractions`` files identify the residential and commercial | ||
| buildings components already present in aggregate ``rc_spec`` and | ||
| ``rc_therm`` so they can be removed before the replacement demand is added. | ||
|
|
||
| Packaged SSP coverage differs across the calibration layers. ``theta`` and | ||
| ``rc_sector_fractions`` ship for SSP1, SSP2, and SSP3. ``gamma`` (the | ||
| ``correction_coefficients`` files) and the STURM floor-area projections are | ||
| SSP2-only, pending additional STURM runs. Buildings impacts under SSP1 or | ||
| SSP3 therefore use SSP-specific ``theta`` and ``rc_sector_fractions`` on top | ||
| of an SSP2 STURM baseline and SSP2 ``gamma``. | ||
|
|
||
| Thermoelectric cooling | ||
| ====================== | ||
|
|
||
| Thermoelectric cooling impacts use | ||
| :file:`message_ix_models/data/impacts/rime/r12_thermoelectric_gwl.nc`. The | ||
| file is R12-coded and has two cooling categories: ``wet`` for freshwater | ||
| once-through and closed-loop cooling, and ``dry`` for air cooling. Ratios are | ||
| computed relative to the 1.0 °C GWL capacity factor. | ||
|
|
||
| Wet and dry cooling use different MESSAGE-side levers. Wet cooling limits | ||
| freshwater-cooled activity, so the application writes relation bounds on | ||
| freshwater once-through and closed-loop cooling technologies. Dry cooling | ||
| reduces air-cooled plant performance, so the application derates | ||
| ``capacity_factor`` rows for ``__air`` technologies. Saline cooling is not | ||
| represented in the packaged RIME cooling dataset and is left unchanged. | ||
|
|
||
| The wet-cooling relation is constructed so that, given the regional freshwater | ||
| share, total freshwater-cooled activity from a parent power technology cannot | ||
| exceed the warming-impaired capacity factor times that parent's activity. | ||
| Dry cooling is represented directly as a multiplicative derating of air-cooled | ||
| capacity factors. | ||
|
|
||
| The impact kernels are based on: | ||
|
|
||
| - Wet cooling: Li et al. (2025), "Global hydroclimatic risks and strategic | ||
| decommissioning pathways for thermal power units." *Nature Sustainability*. | ||
| doi:10.1038/s41893-025-01692-9 | ||
| - Dry cooling: Qin et al. (2023), "Global assessment of the carbon-water | ||
| tradeoff of dry cooling for thermal power generation." *Nature Water*. | ||
| doi:10.1038/s44221-023-00120-6 | ||
|
|
||
| Water availability | ||
| ================== | ||
|
|
||
| Basin-level water impacts use RIME datasets at native 157-basin resolution. | ||
| The packaged water datasets store GWL-indexed conditional summaries for | ||
| ``qtot_mean`` and ``qr`` from CWatM ISIMIP3b realizations. The stored | ||
| variables are the expected value plus selected spread summaries | ||
| (``std``, ``p10``, ``p50``, and ``p90``). The source realizations span five GCMs | ||
| (``gfdl-esm4``, ``ipsl-cm6a-lr``, ``mpi-esm1-2-hr``, ``mri-esm2-0``, | ||
| ``ukesm1-0-ll``) and three SSP-RCP climate scenarios (``ssp126``, | ||
| ``ssp370``, ``ssp585``). The future CWatM runs use | ||
| ``2015soc-from-histsoc`` direct human forcing, so runs differ by climate | ||
| forcing rather than by changing socioeconomic water-use assumptions. The | ||
| RIME datasets are binned with an 11-year centered time window. | ||
|
|
||
| The water application expands those predictions to the MESSAGE basin-region | ||
| rows used by the water module, including transboundary basin splits. This is | ||
| also a domain application layer: :mod:`message_ix_models.tools.impacts` | ||
| predicts emulator values, while :mod:`message_ix_models.model.water.data.impacts` | ||
| owns the basin mapping and water-specific output shapes. | ||
|
|
||
| The current transform preserves the RIME prediction values while changing the | ||
| spatial index from native emulator basins to MESSAGE basin-region rows. Future | ||
| water-CID application work is expected to add the MESSAGE-side hydrology | ||
| semantics on top of that mapping, including groundwater-share construction, | ||
| km3-to-MCM conversion, and the sign convention needed when water availability | ||
| is represented through MESSAGE demand-like parameters. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,73 @@ | ||
| SPARCCLE | ||
| ******** | ||
|
|
||
| “Socioeconomic Pathways, Adaptation and Resilience to Changing CLimate in Europe” | ||
| "Socioeconomic Pathways, Adaptation and Resilience to Changing CLimate in Europe" | ||
|
|
||
| - Project lead: :gh-user:`byersiiasa` | ||
| - Lead modeler: :gh-user:`adrivinca` | ||
|
|
||
| Overview | ||
| ======== | ||
|
|
||
| The SPARCCLE protocol combines socioeconomic starter scenarios with | ||
| climate-impact variants and project-specific clone naming. | ||
|
|
||
| Economic impacts | ||
| ================ | ||
|
|
||
| Economic and GDP-based impacts are part of the broader SPARCCLE protocol. | ||
| They are not implemented by the physical-impact workflow described below. | ||
|
|
||
| Physical climate impacts | ||
| ======================== | ||
|
|
||
| The physical-impact workflow applies climate-impact damage drivers to solved | ||
| MESSAGE starter scenarios. It reads starter-specific GSAT ensembles, evaluates | ||
| the packaged RIME impact emulators, and writes buildings and cooling impacts | ||
| to project-side scenario clones. | ||
|
|
||
| Prerequisites | ||
| ============= | ||
|
|
||
| Each starter needs a MAGICC ``*_IAMC_climateassessment.xlsx`` file in the | ||
| directory configured by | ||
| :file:`message_ix_models/project/sparccle/scenario_config.yaml`. Buildings | ||
| impacts operate on calibrated ``rc_spec`` and ``rc_therm`` demand. Cooling | ||
| impacts require the water-cooling module; the workflow builds this prep clone | ||
| before applying cooling CIDs. | ||
|
|
||
| SSP coverage | ||
| ============ | ||
|
|
||
| Buildings calibration data ships for SSP1, SSP2, and SSP3. Cooling impacts | ||
| do not depend on SSP-specific buildings calibration. | ||
|
|
||
| Running the pipeline | ||
| ==================== | ||
|
|
||
| The CLI builds a workflow graph from | ||
| :file:`message_ix_models/project/sparccle/scenario_config.yaml` and runs | ||
| the requested target step: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| # Buildings only | ||
| mix-models sparccle run "<MODEL>/<SCENARIO> CI_b" --go | ||
|
|
||
| # Cooling only (wet + dry, on a cooling-built prep clone) | ||
| mix-models sparccle run "<MODEL>/<SCENARIO> CI_p" --go | ||
|
|
||
| # Combined buildings + cooling | ||
| mix-models sparccle run "<MODEL>/<SCENARIO> CI_bp" --go | ||
|
|
||
| Each target writes a suffixed clone: | ||
|
|
||
| - ``<scenario>_CI_b`` — buildings demand replaced under | ||
| ``Final Energy|Residential and Commercial|{Cooling,Heating}``. | ||
| - ``<scenario>_cooling_CI_p`` — wet-cooling activity bounds and dry-cooling | ||
| capacity-factor derating applied; ratios persisted as | ||
| ``Physical Climate Impact|Thermoelectric Cooling|*`` timeseries. | ||
| - ``<scenario>_cooling_CI_bp`` — both, in one workflow step. | ||
|
|
||
| See :doc:`/impacts/index` for the impact application modules and | ||
| :doc:`/api/tools-impacts` for the underlying GMT-to-impact toolkit. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.