Source code for openscm_runner.adapters.fair_adapter.fair_adapter

"""
FAIR adapter
"""
import functools
import os

import numpy as np
import pandas as pd
from scmdata import ScmRun

from ...progress import progress
from ..base import _Adapter
from ._compat import fair
from ._run_fair import run_fair
from ._scmdf_to_emissions import scmdf_to_emissions


@functools.lru_cache
def _get_natural_emissions_and_forcing(startyear, num_timesteps):
    # TODO: somebody who knows what they are doing to use scmdata
    natural_df = pd.read_csv(
        os.path.join(
            os.path.dirname(__file__),
            "natural-emissions-and-forcing.csv",
        ),
    )
    ndf_values = natural_df.values

    n_index_columns = 7
    start_index = startyear - 1750 + n_index_columns
    ch4_n2o = ndf_values[0:2, start_index : start_index + num_timesteps].T
    solar_forcing = ndf_values[2, start_index : start_index + num_timesteps].T
    volcanic_forcing = ndf_values[3, start_index : start_index + num_timesteps].T

    return {
        "ch4_n2o": ch4_n2o,
        "solar_forcing": solar_forcing,
        "volcanic_forcing": volcanic_forcing,
    }


[docs]class FAIR(_Adapter): """ Adapter for running FAIR """ model_name = "FaIR" def _init_model(self, *args, **kwargs): if fair is None: raise ImportError("fair is not installed. Run 'pip install fair'") def _run(self, scenarios, cfgs, output_variables, output_config): if output_config is not None: raise NotImplementedError("`output_config` not implemented for FaIR") fair_df = ScmRun(scenarios.timeseries()) full_cfgs = self._make_full_cfgs(fair_df, cfgs) res = run_fair(full_cfgs, output_variables) res["climate_model"] = f"FaIRv{self.get_version()}" return res def _make_full_cfgs(self, scenarios, cfgs): # pylint: disable=R0914 full_cfgs = [] run_id_block = 0 startyear = _check_startyear(cfgs) for (scenario, model), smdf in progress( scenarios.timeseries().groupby(["scenario", "model"]), desc="Creating FaIR emissions inputs", ): smdf_in = ScmRun(smdf) scen_startyear = smdf_in.time_points.years()[0] endyear = smdf_in.time_points.years()[-1] if startyear < 1750: raise ValueError( f"startyear must be 1750 or later ({startyear} specified)" ) if endyear > 2500: raise ValueError( f"endyear must be 2500 or earlier ({endyear} implied by scenario data)" ) emissions = scmdf_to_emissions( smdf_in, startyear=startyear, scen_startyear=scen_startyear, endyear=endyear, ) num_timesteps = emissions.shape[0] natural_components = _get_natural_emissions_and_forcing( startyear, num_timesteps ) ch4_n2o = natural_components["ch4_n2o"] solar_forcing = natural_components["solar_forcing"] volcanic_forcing = natural_components["volcanic_forcing"] scenario_cfg = [ { "scenario": scenario, "model": model, "run_id": run_id_block + i, "emissions": emissions, "natural": ch4_n2o, "F_volcanic": volcanic_forcing, "F_solar": solar_forcing, "efficacy": np.ones(45), "diagnostics": "AR6", "gir_carbon_cycle": True, "temperature_function": "Geoffroy", "aerosol_forcing": "aerocom+ghan2", "fixPre1850RCP": False, "b_tro3": np.array( [1.77871043e-04, 5.80173377e-05, 1.94458719e-04, 2.09151270e-03] ), "tropO3_forcing": "cmip6", "aCO2land": 0.0006394631886297174, "b_aero": np.array([-0.00503, 0.0, 0.0, 0.0, 0.0385, -0.0104, 0.0]), "ghan_params": np.array([1.232, 73.9, 63.0]), "gmst_factor": 1 / 1.04, "ohu_factor": 0.92, "startyear": startyear, **cfg, } for i, cfg in enumerate(cfgs) ] run_id_block += len(scenario_cfg) full_cfgs += scenario_cfg return full_cfgs
[docs] @staticmethod def get_version(): """ Get the FAIR version being used by this adapter Returns ------- str The FAIR version id """ return fair.__version__
def _check_startyear(cfgs): """ Check to see that at most one startyear is defined in the config Returns ------- int startyear Raises ------ ValueError if more that one startyear is defined """ first_startyear = cfgs[0].pop("startyear", 1750) if len(cfgs) > 1: for cfg in cfgs[1:]: this_startyear = cfg.pop("startyear", 1750) if this_startyear != first_startyear: raise ValueError("Can only handle one startyear per scenario ensemble") return first_startyear