Skip to content

Commit fd4cd4d

Browse files
Merge pull request #108 from benmsanderson/fix/cicero-idealised-conc-aerosol-overlay
fix(ciceroscmpy2): hold aerosols at PI for idealised conc-driven runs
2 parents dbbcb55 + 66e1279 commit fd4cd4d

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

changelog/108.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed CICEROSCMPY2 holding aerosol / ozone-precursor emissions at the rising historical baseline on the concentration-driven idealised path (`abrupt-4xCO2`, `1pctCO2`). Because `emstart` is `nyend` there (to keep CO2 concentration-driven), the supplied PI-flat emissions were applied only at the final year and every prior year fell back to the `historical_em` baseline, producing a spurious growing aerosol cooling (~0.6 W/m² ERF drift across a 4xCO2 step). `_build_hybrid_emissions_data` now takes an `overlay_from` argument and applies the supplied emissions from `nystart` for idealised runs, so non-CO2 forcers stay at preindustrial; CO2 is unaffected (concentration-driven via `conc_run`).

src/openscm_runner/adapters/ciceroscm_py2_adapter/ciceroscmpy2_adapter.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,13 @@ def _build_scendata_list(
685685
nyend=nyend,
686686
emstart=scen_emstart,
687687
zero_unsupplied=idealised,
688+
# Idealised runs hold every non-CO2 forcer at PI. On the
689+
# conc-driven path scen_emstart is nyend (keeping CO2
690+
# concentration-driven), but the supplied PI-flat aerosol /
691+
# ozone-precursor emissions must apply across the whole
692+
# window rather than fall back to the rising historical
693+
# baseline. Pin the overlay to nystart for idealised runs.
694+
overlay_from=nystart if idealised else None,
688695
)
689696

690697
conc_data = None
@@ -839,6 +846,7 @@ def _build_hybrid_emissions_data(
839846
nyend: int,
840847
emstart: int,
841848
zero_unsupplied: bool = False,
849+
overlay_from: int | None = None,
842850
):
843851
"""
844852
Build an RCMIP-format emissions DataFrame for one scenario.
@@ -859,6 +867,18 @@ def _build_hybrid_emissions_data(
859867
860868
Parameters
861869
----------
870+
overlay_from
871+
Year from which the user's supplied emissions overwrite the
872+
baseline trajectory. Defaults to ``emstart``. For idealised
873+
concentration-driven runs the model ``emstart`` is ``nyend``
874+
(so CO2 stays concentration-driven), but the supplied PI-flat
875+
aerosol / ozone-precursor emissions must still apply across the
876+
whole window -- otherwise the species fall back to the rising
877+
historical baseline (a spurious growing aerosol cooling that
878+
drifts ERF down through abrupt-4xCO2 / 1pctCO2). Pass
879+
``nystart`` in that case to pin the supplied emissions from the
880+
run start; CO2 is unaffected because it is not supplied on the
881+
conc-driven path (it stays concentration-driven via conc_run).
862882
zero_unsupplied
863883
When ``True``, every species column the user does NOT supply
864884
is overwritten with ``0.0`` across the whole ``[nystart, nyend]``
@@ -881,6 +901,8 @@ def _build_hybrid_emissions_data(
881901

882902
from ..utils.cicero_utils.make_scenario_common import cicero_comp_dict
883903

904+
apply_from = emstart if overlay_from is None else overlay_from
905+
884906
df = (
885907
pd.read_csv(
886908
baseline_em_file, delimiter="\t", index_col=0, skiprows=[1, 2, 3]
@@ -965,7 +987,7 @@ def _build_hybrid_emissions_data(
965987
)
966988
continue
967989
for year, val in user_row.items():
968-
if year in df.index and year >= emstart and not pd.isna(val):
990+
if year in df.index and year >= apply_from and not pd.isna(val):
969991
df.at[year, col] = val * convfactor
970992
overlaid.append(cicero_species)
971993
overlaid_df_cols.add(col)

0 commit comments

Comments
 (0)