def test_w_out_config(self, test_scenarios): with pytest.raises(NotImplementedError): run( scenarios=test_scenarios.filter(scenario=["ssp126"]), climate_models_cfgs={ "CiceroSCM": [ { "model_end": 2100, "Index": 30040, "lambda": 0.540, "akapa": 0.341, "cpi": 0.556, "W": 1.897, "rlamdo": 16.618, "beto": 3.225, "mixed": 107.277, "dirso2_forc": -0.457, "indso2_forc": -0.514, "bc_forc": 0.200, "oc_forc": -0.103, }, ] }, output_variables=("Surface Air Temperature Change", ), out_config={"CiceroSCM": ("With ECS", )}, )
def test_return_config_clash_error(test_scenarios, cfgs): with pytest.raises(ValueError): run( climate_models_cfgs={"MAGICC7": cfgs}, scenarios=test_scenarios.filter(scenario=["ssp126"]), output_variables=("Surface Air Temperature Change", ), out_config={"MAGICC7": ("pf_apply", )}, )
def test_run_out_config_type_error(): error_msg = re.escape( "`out_config` values must be tuples, this isn't the case for " "climate_model: 'model_a'") with pytest.raises(TypeError, match=error_msg): run( climate_models_cfgs={"model_a": ["config list"]}, scenarios="not used", out_config={"model_a": "hi"}, )
def test_run_out_config_conflict_error(): error_msg = re.escape("Found model(s) in `out_config` which are not in " "`climate_models_cfgs`: {'another model'}") with pytest.raises(NotImplementedError): with pytest.warns(UserWarning, match=error_msg): run( climate_models_cfgs={"model_a": ["config list"]}, scenarios="not used", out_config={"another model": ("hi", )}, )
def test_variable_naming(self, test_scenarios): missing_from_fair = ( "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC AFOLU", "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC Fossil and Industrial", "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC AFOLU", "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC Fossil and Industrial", "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC AFOLU", "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC Fossil and Industrial", "Net Atmosphere to Ocean Flux|CO2", "Net Atmosphere to Land Flux|CO2", ) common_variables = [ c for c in self._common_variables if c not in missing_from_fair ] res = run( climate_models_cfgs={"FaIR": ({ "startyear": 1750 }, )}, scenarios=test_scenarios.filter(scenario="ssp126"), output_variables=common_variables, ) missing_vars = set(common_variables) - set(res["variable"]) if missing_vars: raise AssertionError(missing_vars)
def test_variable_naming(self, test_scenarios): """ Test that variable naming is implemented as expecteds """ # pseudo-code # a model might not report all outputs missing_variables = ( "Net Atmosphere to Ocean Flux|CO2", "Net Atmosphere to Land Flux|CO2", ) common_variables = [ c for c in self._common_variables if c not in missing_variables ] # run the model and request all common variables the model reportss res = run( climate_models_cfgs={"climate_model": ({"para1": 3.43},)}, scenarios=test_scenarios.filter(scenario="ssp126"), output_variables=common_variables, ) # check that all expected outputs were returned missing_vars = set(common_variables) - set(res["variable"]) if missing_vars: raise AssertionError(missing_vars)
def test_fair_ocean_factors(test_scenarios): res_default_factors = run( climate_models_cfgs={"FaIR": [{}]}, scenarios=test_scenarios.filter(scenario=["ssp585"]), output_variables=( "Surface Air Ocean Blended Temperature Change", "Heat Uptake|Ocean", "Heat Content|Ocean", ), ) res_custom_factors = run( climate_models_cfgs={ "FaIR": [ { "gmst_factor": np.linspace(0.90, 1.00, 351), # test with array "ohu_factor": 0.93, } ] }, scenarios=test_scenarios.filter(scenario=["ssp585"]), output_variables=( "Surface Air Ocean Blended Temperature Change", "Heat Uptake|Ocean", "Heat Content|Ocean", ), ) assert ( res_default_factors.filter( variable="Surface Air Ocean Blended Temperature Change", region="World", year=2100, scenario="ssp585", ).values != res_custom_factors.filter( variable="Surface Air Ocean Blended Temperature Change", region="World", year=2100, scenario="ssp585", ).values )
def test_run(self, test_scenarios): """ Test that the model can be run, ideally with more than one configuration """ # pseudo-code res = run( climate_models_cfgs={ "climate_model": [ { "para1": "value1", "para2": 1.1 }, { "para1": "value3", "para2": 1.2 }, { "para1": "value5", "para2": 1.3 }, ], }, scenarios=test_scenarios.filter( scenario=["ssp126", "ssp245", "ssp370"]), output_variables=( "output", "var", "list", ), out_config=None, ) assert isinstance(res, ScmRun) assert res["run_id"].min() == 0 assert res["run_id"].max() == 8 assert res.get_unique_meta("climate_model", no_duplicates=True) == "model_name" assert set(res.get_unique_meta("variable")) == set( ["expected", "output", "variables"]) # output value checks e.g. npt.assert_allclose( 2.31, res.filter( variable="Surface Air Temperature Change", region="World", year=2100, scenario="ssp126", ).values.max(), rtol=self._rtol, )
def test_variable_naming(self, test_scenarios): common_variables = self._common_variables res = run( climate_models_cfgs={ "MAGICC7": ({ "core_climatesensitivity": 3 }, ) }, scenarios=test_scenarios.filter(scenario="ssp126"), output_variables=common_variables, ) missing_vars = set(common_variables) - set(res["variable"]) if missing_vars: raise AssertionError(missing_vars)
def test_return_config(test_scenarios, out_config): core_climatesensitivities = [2, 3] rf_total_runmoduses = ["ALL", "CO2"] cfgs = [] for cs in core_climatesensitivities: for runmodus in rf_total_runmoduses: cfgs.append({ "out_dynamic_vars": [ "DAT_TOTAL_INCLVOLCANIC_ERF", "DAT_SURFACE_TEMP", ], "core_climatesensitivity": cs, "rf_total_runmodus": runmodus, }) res = run( climate_models_cfgs={"MAGICC7": cfgs}, scenarios=test_scenarios.filter( scenario=["ssp126", "ssp245", "ssp370"]), output_variables=( "Surface Air Temperature Change", "Effective Radiative Forcing", ), out_config={"MAGICC7": out_config}, ) for k in out_config: assert k in res.meta.columns ssp126 = res.filter(scenario="ssp126") # check all the configs were used and check that each scenario # has all the configs included in the metadata too if k == "core_climatesensitivity": assert set( res.get_unique_meta(k)) == set(core_climatesensitivities) assert set( ssp126.get_unique_meta(k)) == set(core_climatesensitivities) elif k == "rf_total_runmodus": assert set(res.get_unique_meta(k)) == set(rf_total_runmoduses) assert set(ssp126.get_unique_meta(k)) == set(rf_total_runmoduses) else: raise NotImplementedError(k)
def test_run( self, test_scenarios, test_data_dir, update_expected_values, shuffle_column_order, ): expected_output_file = os.path.join( test_data_dir, "expected-integration-output", "expected_ciceroscm_test_run_output.json", ) if shuffle_column_order: tmp = test_scenarios.data cols = tmp.columns.tolist() tmp = tmp[cols[1:] + cols[:1]] test_scenarios = ScmRun(test_scenarios) res = run( scenarios=test_scenarios.filter( scenario=["ssp126", "ssp245", "ssp370"]), climate_models_cfgs={ "CICEROSCM": [ { "model_end": 2100, "Index": 30040, "lambda": 0.540, "akapa": 0.341, "cpi": 0.556, "W": 1.897, "rlamdo": 16.618, "beto": 3.225, "mixed": 107.277, "dirso2_forc": -0.457, "indso2_forc": -0.514, "bc_forc": 0.200, "oc_forc": -0.103, }, { "model_end": 2100, "Index": 1, "lambda": 0.3925, "akapa": 0.2421, "cpi": 0.3745, "W": 0.8172, "rlamdo": 16.4599, "beto": 4.4369, "mixed": 35.4192, "dirso2_forc": -0.3428, "indso2_forc": -0.3856, "bc_forc": 0.1507, "oc_forc": -0.0776, }, ] }, output_variables=( "Surface Air Temperature Change", "Surface Air Ocean Blended Temperature Change", "Heat Content|Ocean", "Effective Radiative Forcing", "Effective Radiative Forcing|Anthropogenic", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|Greenhouse Gases", "Heat Uptake", "Atmospheric Concentrations|CO2", "Atmospheric Concentrations|CH4", "Atmospheric Concentrations|N2O", "Emissions|CO2", "Emissions|CH4", "Emissions|N2O", ), out_config=None, ) assert isinstance(res, ScmRun) assert res["run_id"].min() == 1 assert res["run_id"].max() == 30040 assert res.get_unique_meta("climate_model", no_duplicates=True) == "CICERO-SCM" assert set(res.get_unique_meta("variable")) == set([ "Surface Air Temperature Change", "Surface Air Ocean Blended Temperature Change", "Heat Content|Ocean", "Effective Radiative Forcing", "Effective Radiative Forcing|Anthropogenic", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|Greenhouse Gases", "Heat Uptake", "Atmospheric Concentrations|CO2", "Atmospheric Concentrations|CH4", "Atmospheric Concentrations|N2O", "Emissions|CO2", "Emissions|N2O", "Emissions|CH4", ]) # check we can also calcluate quantiles assert "run_id" in res.meta quantiles = calculate_quantiles(res, [0, 0.05, 0.17, 0.5, 0.83, 0.95, 1]) assert "run_id" not in quantiles.meta assert (res.filter( variable="Atmospheric Concentrations|CO2").get_unique_meta( "unit", True) == "ppm") assert (res.filter( variable="Atmospheric Concentrations|CH4").get_unique_meta( "unit", True) == "ppb") assert (res.filter( variable="Atmospheric Concentrations|N2O").get_unique_meta( "unit", True) == "ppb") assert (res.filter(variable="Emissions|CO2").get_unique_meta( "unit", True) == "PgC / yr") assert (res.filter(variable="Emissions|CH4").get_unique_meta( "unit", True) == "TgCH4 / yr") assert (res.filter(variable="Emissions|N2O").get_unique_meta( "unit", True) == "TgN2ON / yr") # check that emissions were passed through correctly for (scen, variable, unit, exp_val) in ( ("ssp126", "Emissions|CO2", "PgC/yr", -2.3503), ("ssp370", "Emissions|CO2", "PgC/yr", 22.562), ("ssp126", "Emissions|CH4", "TgCH4/yr", 122.195), ("ssp370", "Emissions|CH4", "TgCH4/yr", 777.732), ("ssp126", "Emissions|N2O", "TgN2ON/yr", 5.318), ("ssp370", "Emissions|N2O", "TgN2ON/yr", 13.144), ): res_scen_2100_emms = res.filter(variable=variable, year=2100, scenario=scen).convert_unit(unit) if res_scen_2100_emms.empty: raise AssertionError("No {} data for {}".format( variable, scen)) npt.assert_allclose( res_scen_2100_emms.values, exp_val, rtol=1e-4, ) for (scen, variable, unit, exp_val14, exp_val16) in ( ("ssp126", "Emissions|CH4", "TgCH4/yr", 387.874, 379.956), ("ssp370", "Emissions|CH4", "TgCH4/yr", 387.874, 394.149), ("ssp126", "Emissions|N2O", "TgN2ON/yr", 6.911, 6.858), ("ssp370", "Emissions|N2O", "TgN2ON/yr", 6.911, 7.0477), ): res_scen_2014_emms = res.filter(variable=variable, year=2014, scenario=scen).convert_unit(unit) if res_scen_2014_emms.empty: raise AssertionError("No {} data for {}".format( variable, scen)) res_scen_2016_emms = res.filter(variable=variable, year=2016, scenario=scen).convert_unit(unit) if res_scen_2016_emms.empty: raise AssertionError("No {} data for {}".format( variable, scen)) npt.assert_allclose( res_scen_2014_emms.values, exp_val14, rtol=1e-4, ) npt.assert_allclose( res_scen_2016_emms.values, exp_val16, rtol=1e-4, ) for (scen, variable) in ( ("ssp126", "Effective Radiative Forcing|Aerosols"), ("ssp370", "Effective Radiative Forcing|Aerosols"), ): res_scen_2015_emms = res.filter(variable=variable, year=2015, scenario=scen) if res_scen_2015_emms.empty: raise AssertionError( "No CO2 emissions data for {}".format(scen)) assert not np.equal(res_scen_2015_emms.values, 0).all() ssp245_ghg_erf_2015 = res.filter( variable="Effective Radiative Forcing|Greenhouse Gases", year=2015, scenario="ssp245", run_id=1, ) ssp245_ghg_erf_2014 = res.filter( variable="Effective Radiative Forcing|Greenhouse Gases", year=2014, scenario="ssp245", run_id=1, ) # check that jump in GHG ERF isn't there assert (ssp245_ghg_erf_2015.values.squeeze() - ssp245_ghg_erf_2014.values.squeeze()) < 0.1 ssp245_ch4_conc_2015 = res.filter( variable="Atmospheric Concentrations|CH4", year=2015, scenario="ssp245", run_id=1, ) ssp245_ch4_conc_2014 = res.filter( variable="Atmospheric Concentrations|CH4", year=2014, scenario="ssp245", run_id=1, ) # ch # check that jump in GHG ERF isn't there assert (ssp245_ch4_conc_2014.values.squeeze() - ssp245_ch4_conc_2015.values.squeeze()) < 0.1 self._check_output(res, expected_output_file, update_expected_values)
scenarios = pyam.IamDataFrame(data_file_scenarios) assert MAGICC7.get_version() == EXPECTED_MAGICC_VERSION, MAGICC7.get_version() res = run( climate_models_cfgs={ "MAGICC7": [ { "core_climatesensitivity": 3, "rf_soxi_dir_wm2": -0.2, "out_temperature": 1, }, { "core_climatesensitivity": 2, "rf_soxi_dir_wm2": -0.1, "out_temperature": 1, }, { "core_climatesensitivity": 5, "rf_soxi_dir_wm2": -0.35, "out_temperature": 1, }, ], }, scenarios=scenarios, ) if UPDATE: res.to_csv(data_file_regression) else: expected_res = pyam.IamDataFrame(data_file_regression)
def test_magicc7_run(test_scenarios, magicc7_is_available): debug_run = False res = run( climate_models_cfgs={ "MAGICC7": [ { "core_climatesensitivity": 3, "rf_soxi_dir_wm2": -0.2, "out_temperature": 1, "out_forcing": 1, "out_dynamic_vars": [ "DAT_AEROSOL_ERF", "DAT_HEATCONTENT_AGGREG_TOTAL", "DAT_CO2_AIR2LAND_FLUX", ], "out_ascii_binary": "BINARY", "out_binary_format": 2, }, { "core_climatesensitivity": 2, "rf_soxi_dir_wm2": -0.1, "out_temperature": 1, "out_forcing": 1, "out_ascii_binary": "BINARY", "out_binary_format": 2, }, { "core_climatesensitivity": 5, "rf_soxi_dir_wm2": -0.35, "out_temperature": 1, "out_forcing": 1, "out_ascii_binary": "BINARY", "out_binary_format": 2, }, ], }, scenarios=test_scenarios.filter( scenario=["ssp126", "ssp245", "ssp370"]), output_variables=( "Surface Temperature", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", "Heat Content|Ocean", "Net Atmosphere to Land Flux|CO2", ), ) assert isinstance(res, ScmRun) assert res["run_id"].min() == 0 assert res["run_id"].max() == 8 assert res.get_unique_meta("climate_model", no_duplicates=True) == "MAGICC{}".format( MAGICC7.get_version()) assert set(res.get_unique_meta("variable")) == set([ "Surface Temperature", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", "Heat Content|Ocean", "Net Atmosphere to Land Flux|CO2", ]) # check ocean heat content unit conversion comes through correctly _check_res( 1824.05, res.filter( unit="ZJ", variable="Heat Content|Ocean", region="World", year=2100, scenario="ssp126", ).values.max(), not debug_run, rtol=RTOL, ) _check_res( 0.472378, res.filter( unit="GtC / yr", variable="Net Atmosphere to Land Flux|CO2", region="World", year=2100, scenario="ssp126", ).values.max(), not debug_run, rtol=RTOL, ) _check_res( 2.756034, res.filter(variable="Surface Temperature", region="World", year=2100, scenario="ssp126").values.max(), not debug_run, rtol=RTOL, ) _check_res( 1.2195495, res.filter(variable="Surface Temperature", region="World", year=2100, scenario="ssp126").values.min(), not debug_run, rtol=RTOL, ) _check_res( 5.5226571, res.filter(variable="Surface Temperature", region="World", year=2100, scenario="ssp370").values.max(), not debug_run, rtol=RTOL, ) _check_res( 2.733369581, res.filter(variable="Surface Temperature", region="World", year=2100, scenario="ssp370").values.min(), not debug_run, rtol=RTOL, ) # check we can also calcluate quantiles quantiles = calculate_quantiles(res, [0.05, 0.17, 0.5, 0.83, 0.95]) _check_res( 1.27586919, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", quantile=0.05, ).values, not debug_run, rtol=RTOL, ) _check_res( 2.6587052, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", quantile=0.95, ).values, not debug_run, rtol=RTOL, ) _check_res( 2.83627686, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", quantile=0.05, ).values, not debug_run, rtol=RTOL, ) _check_res( 5.34663565, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", quantile=0.95, ).values, not debug_run, rtol=RTOL, ) if debug_run: assert False, "Turn off debug"
def test_forcing_categories(test_scenarios): forcing_categories = [ "Effective Radiative Forcing|CO2", "Effective Radiative Forcing|CH4", "Effective Radiative Forcing|N2O", "Effective Radiative Forcing|CF4", "Effective Radiative Forcing|C2F6", "Effective Radiative Forcing|C6F14", "Effective Radiative Forcing|HFC23", "Effective Radiative Forcing|HFC32", "Effective Radiative Forcing|HFC125", "Effective Radiative Forcing|HFC134a", "Effective Radiative Forcing|HFC143a", "Effective Radiative Forcing|HFC227ea", "Effective Radiative Forcing|HFC245fa", "Effective Radiative Forcing|HFC4310mee", "Effective Radiative Forcing|SF6", "Effective Radiative Forcing|CFC11", "Effective Radiative Forcing|CFC12", "Effective Radiative Forcing|CFC113", "Effective Radiative Forcing|CFC114", "Effective Radiative Forcing|CFC115", "Effective Radiative Forcing|CCl4", "Effective Radiative Forcing|CH3CCl3", "Effective Radiative Forcing|HCFC22", "Effective Radiative Forcing|HCFC141b", "Effective Radiative Forcing|HCFC142b", "Effective Radiative Forcing|Halon1211", "Effective Radiative Forcing|Halon1202", "Effective Radiative Forcing|Halon1301", "Effective Radiative Forcing|Halon2402", "Effective Radiative Forcing|CH3Br", "Effective Radiative Forcing|CH3Cl", "Effective Radiative Forcing|Tropospheric Ozone", "Effective Radiative Forcing|Stratospheric Ozone", "Effective Radiative Forcing|CH4 Oxidation Stratospheric H2O", "Effective Radiative Forcing|Contrails", "Effective Radiative Forcing|Aerosols|Direct Effect|SOx", "Effective Radiative Forcing|Aerosols|Direct Effect|Secondary Organic Aerosol", "Effective Radiative Forcing|Aerosols|Direct Effect|Nitrate", "Effective Radiative Forcing|Aerosols|Direct Effect|BC", "Effective Radiative Forcing|Aerosols|Direct Effect|OC", "Effective Radiative Forcing|Aerosols|Indirect Effect", "Effective Radiative Forcing|Black Carbon on Snow", "Effective Radiative Forcing|Land-use Change", "Effective Radiative Forcing|Volcanic", "Effective Radiative Forcing|Solar", "Effective Radiative Forcing", "Effective Radiative Forcing|Anthropogenic", "Effective Radiative Forcing|Greenhouse Gases", "Effective Radiative Forcing|Kyoto Gases", "Effective Radiative Forcing|CO2, CH4 and N2O", "Effective Radiative Forcing|F-Gases", "Effective Radiative Forcing|Montreal Protocol Halogen Gases", "Effective Radiative Forcing|Aerosols|Direct Effect", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|Ozone", "Effective Radiative Forcing", ] res = run( climate_models_cfgs={"FaIR": [{}]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=tuple(forcing_categories), out_config=None, ) # storing results in a dict makes this a bit more compact forcing = {} for variable in forcing_categories: forcing[variable] = res.filter(variable=variable, region="World").values npt.assert_allclose( forcing["Effective Radiative Forcing|CO2"] + forcing["Effective Radiative Forcing|CH4"] + forcing["Effective Radiative Forcing|N2O"] + forcing["Effective Radiative Forcing|CF4"] + forcing["Effective Radiative Forcing|C2F6"] + forcing["Effective Radiative Forcing|C6F14"] + forcing["Effective Radiative Forcing|HFC23"] + forcing["Effective Radiative Forcing|HFC32"] + forcing["Effective Radiative Forcing|HFC125"] + forcing["Effective Radiative Forcing|HFC134a"] + forcing["Effective Radiative Forcing|HFC143a"] + forcing["Effective Radiative Forcing|HFC227ea"] + forcing["Effective Radiative Forcing|HFC245fa"] + forcing["Effective Radiative Forcing|HFC4310mee"] + forcing["Effective Radiative Forcing|SF6"] + forcing["Effective Radiative Forcing|CFC11"] + forcing["Effective Radiative Forcing|CFC12"] + forcing["Effective Radiative Forcing|CFC113"] + forcing["Effective Radiative Forcing|CFC114"] + forcing["Effective Radiative Forcing|CFC115"] + forcing["Effective Radiative Forcing|CCl4"] + forcing["Effective Radiative Forcing|CH3CCl3"] + forcing["Effective Radiative Forcing|HCFC22"] + forcing["Effective Radiative Forcing|HCFC141b"] + forcing["Effective Radiative Forcing|HCFC142b"] + forcing["Effective Radiative Forcing|Halon1211"] + forcing["Effective Radiative Forcing|Halon1202"] + forcing["Effective Radiative Forcing|Halon1301"] + forcing["Effective Radiative Forcing|Halon2402"] + forcing["Effective Radiative Forcing|CH3Br"] + forcing["Effective Radiative Forcing|CH3Cl"], forcing[ "Effective Radiative Forcing|Greenhouse Gases"], # should this be "well mixed" greenhouse gases? ) npt.assert_allclose( forcing["Effective Radiative Forcing|CO2"] + forcing["Effective Radiative Forcing|CH4"] + forcing["Effective Radiative Forcing|N2O"] + forcing["Effective Radiative Forcing|CF4"] + forcing["Effective Radiative Forcing|C2F6"] + forcing["Effective Radiative Forcing|C6F14"] + forcing["Effective Radiative Forcing|HFC23"] + forcing["Effective Radiative Forcing|HFC32"] + forcing["Effective Radiative Forcing|HFC125"] + forcing["Effective Radiative Forcing|HFC134a"] + forcing["Effective Radiative Forcing|HFC143a"] + forcing["Effective Radiative Forcing|HFC227ea"] + forcing["Effective Radiative Forcing|HFC245fa"] + forcing["Effective Radiative Forcing|HFC4310mee"] + forcing["Effective Radiative Forcing|SF6"], forcing["Effective Radiative Forcing|Kyoto Gases"], ) npt.assert_allclose( forcing["Effective Radiative Forcing|CO2"] + forcing["Effective Radiative Forcing|CH4"] + forcing["Effective Radiative Forcing|N2O"], forcing["Effective Radiative Forcing|CO2, CH4 and N2O"], ) npt.assert_allclose( forcing["Effective Radiative Forcing|CF4"] + forcing["Effective Radiative Forcing|C2F6"] + forcing["Effective Radiative Forcing|C6F14"] + forcing["Effective Radiative Forcing|HFC23"] + forcing["Effective Radiative Forcing|HFC32"] + forcing["Effective Radiative Forcing|HFC125"] + forcing["Effective Radiative Forcing|HFC134a"] + forcing["Effective Radiative Forcing|HFC143a"] + forcing["Effective Radiative Forcing|HFC227ea"] + forcing["Effective Radiative Forcing|HFC245fa"] + forcing["Effective Radiative Forcing|HFC4310mee"] + forcing["Effective Radiative Forcing|SF6"], forcing["Effective Radiative Forcing|F-Gases"], ) npt.assert_allclose( forcing["Effective Radiative Forcing|CFC11"] + forcing["Effective Radiative Forcing|CFC12"] + forcing["Effective Radiative Forcing|CFC113"] + forcing["Effective Radiative Forcing|CFC114"] + forcing["Effective Radiative Forcing|CFC115"] + forcing["Effective Radiative Forcing|CCl4"] + forcing["Effective Radiative Forcing|CH3CCl3"] + forcing["Effective Radiative Forcing|HCFC22"] + forcing["Effective Radiative Forcing|HCFC141b"] + forcing["Effective Radiative Forcing|HCFC142b"] + forcing["Effective Radiative Forcing|Halon1211"] + forcing["Effective Radiative Forcing|Halon1202"] + forcing["Effective Radiative Forcing|Halon1301"] + forcing["Effective Radiative Forcing|Halon2402"] + forcing["Effective Radiative Forcing|CH3Br"] + forcing["Effective Radiative Forcing|CH3Cl"], forcing["Effective Radiative Forcing|Montreal Protocol Halogen Gases"], ) npt.assert_allclose( forcing["Effective Radiative Forcing|Tropospheric Ozone"] + forcing["Effective Radiative Forcing|Stratospheric Ozone"], forcing["Effective Radiative Forcing|Ozone"], ) npt.assert_allclose( forcing["Effective Radiative Forcing|Aerosols|Direct Effect|SOx"] + forcing[ "Effective Radiative Forcing|Aerosols|Direct Effect|Secondary Organic Aerosol"] + forcing["Effective Radiative Forcing|Aerosols|Direct Effect|Nitrate"] + forcing["Effective Radiative Forcing|Aerosols|Direct Effect|BC"] + forcing["Effective Radiative Forcing|Aerosols|Direct Effect|OC"], forcing["Effective Radiative Forcing|Aerosols|Direct Effect"], ) # If up to here is fine, then we only need to check previouly defined aggregates against "super-aggregates" npt.assert_allclose( forcing["Effective Radiative Forcing|Aerosols|Direct Effect"] + forcing["Effective Radiative Forcing|Aerosols|Indirect Effect"], forcing["Effective Radiative Forcing|Aerosols"], ) npt.assert_allclose( forcing["Effective Radiative Forcing|Greenhouse Gases"] + forcing["Effective Radiative Forcing|Ozone"] + forcing["Effective Radiative Forcing|CH4 Oxidation Stratospheric H2O"] + forcing["Effective Radiative Forcing|Contrails"] + forcing["Effective Radiative Forcing|Aerosols"] + forcing["Effective Radiative Forcing|Black Carbon on Snow"] + forcing["Effective Radiative Forcing|Land-use Change"], forcing["Effective Radiative Forcing|Anthropogenic"], ) npt.assert_allclose( forcing["Effective Radiative Forcing|Anthropogenic"] + forcing["Effective Radiative Forcing|Volcanic"] + forcing["Effective Radiative Forcing|Solar"], forcing["Effective Radiative Forcing"], )
def test_startyear(test_scenarios, test_scenarios_2600): # we can't run different start years in the same ensemble as output files will differ in shape. # There is a separate test to ensure this does raise an error. res_1850 = run( climate_models_cfgs={"FaIR": [{ "startyear": 1850 }]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change", ), out_config=None, ) res_1750 = run( climate_models_cfgs={"FaIR": [{ "startyear": 1750 }]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change", ), out_config=None, ) res_default = run( climate_models_cfgs={"FaIR": [{}]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change", ), out_config=None, ) gsat2100_start1850 = res_1850.filter( variable="Surface Air Temperature Change", region="World", year=2100, ).values gsat2100_start1750 = res_1750.filter( variable="Surface Air Temperature Change", region="World", year=2100, ).values gsat2100_startdefault = res_default.filter( variable="Surface Air Temperature Change", region="World", year=2100, ).values assert gsat2100_start1850 != gsat2100_start1750 assert gsat2100_start1750 == gsat2100_startdefault with pytest.raises(ValueError): run( climate_models_cfgs={"FaIR": [{ "startyear": 1650 }]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change", ), out_config=None, ) with pytest.raises(ValueError): run( climate_models_cfgs={"FaIR": [{}]}, scenarios=test_scenarios_2600.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change", ), out_config=None, ) with pytest.raises(ValueError): run( climate_models_cfgs={ "FaIR": [{ "startyear": 1750 }, { "startyear": 1850 }] }, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change", ), out_config=None, )
def test_run( self, test_scenarios, monkeypatch, nworkers, test_data_dir, update_expected_values, ): expected_output_file = os.path.join( test_data_dir, "expected-integration-output", "expected_fair1X_test_run_output.json", ) monkeypatch.setenv("FAIR_WORKER_NUMBER", "{}".format(nworkers)) res = run( climate_models_cfgs={ "FaIR": [ {}, { "q": np.array([0.3, 0.45]), "r0": 30.0, "lambda_global": 0.9 }, { "q": np.array([0.35, 0.4]), "r0": 25.0, "lambda_global": 1.1 }, ], }, scenarios=test_scenarios.filter( scenario=["ssp126", "ssp245", "ssp370"]), output_variables=( "Surface Air Temperature Change", "Atmospheric Concentrations|CO2", "Heat Content", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", "CO2 Air to Land Flux", # should be ignored ), out_config=None, ) assert isinstance(res, ScmRun) assert res["run_id"].min() == 0 assert res["run_id"].max() == 8 assert res.get_unique_meta("climate_model", no_duplicates=True) == "FaIRv{}".format( FAIR.get_version()) assert set(res.get_unique_meta("variable")) == set([ "Surface Air Temperature Change", "Atmospheric Concentrations|CO2", "Heat Content", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", ]) # check we can also calcluate quantiles assert "run_id" in res.meta quantiles = calculate_quantiles(res, [0, 0.05, 0.17, 0.5, 0.83, 0.95, 1]) assert "run_id" not in quantiles.meta self._check_output(res, expected_output_file, update_expected_values)
def test_multimodel_run(test_scenarios, magicc7_is_available): debug_run = False res = run( climate_models_cfgs={ "FaIR": [ {}, { "q": np.array([0.3, 0.45]), "r0": 30.0, "lambda_global": 0.9 }, { "q": np.array([0.35, 0.4]), "r0": 25.0, "lambda_global": 1.1 }, ], "MAGICC7": [ { "core_climatesensitivity": 3, "rf_soxi_dir_wm2": -0.2, "out_temperature": 1, "out_forcing": 1, "out_dynamic_vars": [ "DAT_CO2_CONC", "DAT_AEROSOL_ERF", "DAT_HEATCONTENT_AGGREG_TOTAL", "DAT_HEATUPTK_AGGREG", ], "out_ascii_binary": "BINARY", "out_binary_format": 2, }, { "core_climatesensitivity": 2, "rf_soxi_dir_wm2": -0.1, "out_temperature": 1, "out_forcing": 1, "out_dynamic_vars": [ "DAT_CO2_CONC", "DAT_AEROSOL_ERF", "DAT_HEATCONTENT_AGGREG_TOTAL", "DAT_HEATUPTK_AGGREG", ], "out_ascii_binary": "BINARY", "out_binary_format": 2, }, { "core_climatesensitivity": 5, "rf_soxi_dir_wm2": -0.35, "out_temperature": 1, "out_forcing": 1, "out_dynamic_vars": [ "DAT_CO2_CONC", "DAT_AEROSOL_ERF", "DAT_HEATCONTENT_AGGREG_TOTAL", "DAT_HEATUPTK_AGGREG", ], "out_ascii_binary": "BINARY", "out_binary_format": 2, }, ], }, scenarios=test_scenarios.filter( scenario=["ssp126", "ssp245", "ssp370"]), output_variables=( "Surface Temperature", "Atmospheric Concentrations|CO2", "Heat Content|Ocean", "Heat Uptake|Ocean", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", ), out_config=None, ) assert isinstance(res, ScmRun) climate_models = res.get_unique_meta("climate_model") assert any(["MAGICC" in m for m in climate_models]) assert any(["FaIR" in m for m in climate_models]) for climate_model in climate_models: res_cm = res.filter(climate_model=climate_model) assert set(res_cm.get_unique_meta("variable")) == set([ "Surface Temperature", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", "Heat Content|Ocean", "Heat Uptake|Ocean", "Atmospheric Concentrations|CO2", ]) quantiles = calculate_quantiles(res, [0.05, 0.17, 0.5, 0.83, 0.95]) _check_res( 1.3603486, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", quantile=0.05, ).values, not debug_run, rtol=RTOL, ) _check_res( 2.61950384, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", quantile=0.95, ).values, not debug_run, rtol=RTOL, ) _check_res( 2.99063777, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", quantile=0.05, ).values, not debug_run, rtol=RTOL, ) _check_res( 5.34821243, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", quantile=0.95, ).values, not debug_run, rtol=RTOL, ) quantiles_cm = calculate_quantiles( res, [0.05, 0.17, 0.5, 0.83, 0.95], process_over_columns=("run_id", "ensemble_member"), ) _check_res( 1.27586919, quantiles_cm.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", quantile=0.05, climate_model="MAGICC*", ).values, not debug_run, rtol=RTOL, ) _check_res( 5.34663565, quantiles_cm.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", quantile=0.95, climate_model="MAGICC*", ).values, not debug_run, rtol=RTOL, ) _check_res( 1.80924238, quantiles_cm.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", quantile=0.05, climate_model="FaIR*", ).values, not debug_run, rtol=RTOL, ) _check_res( 4.76399179, quantiles_cm.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", quantile=0.95, climate_model="FaIR*", ).values, not debug_run, rtol=RTOL, ) if debug_run: assert False, "Turn off debug"
def test_run( self, test_scenarios, test_data_dir, update_expected_values, ): expected_output_file = os.path.join( test_data_dir, "expected-integration-output", "expected_magicc7_test_run_output.json", ) res = run( climate_models_cfgs={ "MAGICC7": [ { "core_climatesensitivity": 3, "rf_soxi_dir_wm2": -0.2, "out_temperature": 1, "out_forcing": 1, "out_dynamic_vars": [ "DAT_AEROSOL_ERF", "DAT_HEATCONTENT_AGGREG_TOTAL", "DAT_CO2_AIR2LAND_FLUX", ], "out_ascii_binary": "BINARY", "out_binary_format": 2, }, { "core_climatesensitivity": 2, "rf_soxi_dir_wm2": -0.1, "out_temperature": 1, "out_forcing": 1, "out_ascii_binary": "BINARY", "out_binary_format": 2, }, { "core_climatesensitivity": 5, "rf_soxi_dir_wm2": -0.35, "out_temperature": 1, "out_forcing": 1, "out_ascii_binary": "BINARY", "out_binary_format": 2, }, ], }, scenarios=test_scenarios.filter( scenario=["ssp126", "ssp245", "ssp370"]), output_variables=( "Surface Air Temperature Change", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", "Heat Content|Ocean", "Net Atmosphere to Land Flux|CO2", ), ) assert isinstance(res, ScmRun) assert res["run_id"].min() == 0 assert res["run_id"].max() == 8 assert res.get_unique_meta("climate_model", no_duplicates=True) == "MAGICC{}".format( MAGICC7.get_version()) assert set(res.get_unique_meta("variable")) == set([ "Surface Air Temperature Change", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", "Heat Content|Ocean", "Net Atmosphere to Land Flux|CO2", ]) # check we can also calcluate quantiles assert "run_id" in res.meta quantiles = calculate_quantiles(res, [0, 0.05, 0.17, 0.5, 0.83, 0.95, 1]) assert "run_id" not in quantiles.meta self._check_output(res, expected_output_file, update_expected_values)
def test_multimodel_run(test_scenarios, test_data_dir, update_expected_values): expected_output_file = os.path.join( test_data_dir, "expected-integration-output", "expected_run_multimodel_output.json", ) res = run( climate_models_cfgs={ "FaIR": [ {}, {"q": np.array([0.3, 0.45]), "r0": 30.0, "lambda_global": 0.9}, {"q": np.array([0.35, 0.4]), "r0": 25.0, "lambda_global": 1.1}, ], "MAGICC7": [ { "core_climatesensitivity": 3, "rf_soxi_dir_wm2": -0.2, "out_temperature": 1, "out_forcing": 1, "out_dynamic_vars": [ "DAT_CO2_CONC", "DAT_AEROSOL_ERF", "DAT_HEATCONTENT_AGGREG_TOTAL", "DAT_HEATUPTK_AGGREG", ], "out_ascii_binary": "BINARY", "out_binary_format": 2, }, { "core_climatesensitivity": 2, "rf_soxi_dir_wm2": -0.1, "out_temperature": 1, "out_forcing": 1, "out_dynamic_vars": [ "DAT_CO2_CONC", "DAT_AEROSOL_ERF", "DAT_HEATCONTENT_AGGREG_TOTAL", "DAT_HEATUPTK_AGGREG", ], "out_ascii_binary": "BINARY", "out_binary_format": 2, }, { "core_climatesensitivity": 5, "rf_soxi_dir_wm2": -0.35, "out_temperature": 1, "out_forcing": 1, "out_dynamic_vars": [ "DAT_CO2_CONC", "DAT_AEROSOL_ERF", "DAT_HEATCONTENT_AGGREG_TOTAL", "DAT_HEATUPTK_AGGREG", ], "out_ascii_binary": "BINARY", "out_binary_format": 2, }, ], }, scenarios=test_scenarios.filter(scenario=["ssp126", "ssp245", "ssp370"]), output_variables=( "Surface Air Temperature Change", "Atmospheric Concentrations|CO2", "Heat Content|Ocean", "Heat Uptake|Ocean", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", ), out_config=None, ) assert isinstance(res, ScmRun) climate_models = res.get_unique_meta("climate_model") assert any(["MAGICC" in m for m in climate_models]) assert any(["FaIR" in m for m in climate_models]) for climate_model in climate_models: res_cm = res.filter(climate_model=climate_model) assert set(res_cm.get_unique_meta("variable")) == set( [ "Surface Air Temperature Change", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", "Heat Content|Ocean", "Heat Uptake|Ocean", "Atmospheric Concentrations|CO2", ] ) # check we can also calcluate quantiles assert "run_id" in res.meta quantiles = calculate_quantiles(res, [0, 0.05, 0.17, 0.5, 0.83, 0.95, 1]) assert "run_id" not in quantiles.meta openscm_runner.testing._check_output( res, expected_output_file, rtol=RTOL, update=update_expected_values )
def test_fair_run(test_scenarios): res = run( climate_models_cfgs={ "FaIR": [ {}, { "q": np.array([0.3, 0.45]), "r0": 30.0, "lambda_global": 0.9 }, { "q": np.array([0.35, 0.4]), "r0": 25.0, "lambda_global": 1.1 }, ], }, scenarios=test_scenarios.filter( scenario=["ssp126", "ssp245", "ssp370"]), output_variables=( "Surface Temperature", "Atmospheric Concentrations|CO2", "Heat Content", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", "CO2 Air to Land Flux", # should be ignored ), out_config=None, ) assert isinstance(res, ScmRun) assert res["run_id"].min() == 0 assert res["run_id"].max() == 8 assert res.get_unique_meta("climate_model", no_duplicates=True) == "FaIRv{}".format( FAIR.get_version()) assert set(res.get_unique_meta("variable")) == set([ "Surface Temperature", "Atmospheric Concentrations|CO2", "Heat Content", "Effective Radiative Forcing", "Effective Radiative Forcing|Aerosols", "Effective Radiative Forcing|CO2", ]) npt.assert_allclose( 2.2099132544445927, res.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", ).values.max(), rtol=RTOL, ) npt.assert_allclose( 1.7945341435607594, res.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", ).values.min(), rtol=RTOL, ) npt.assert_allclose( 4.824878345585957, res.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", ).values.max(), rtol=RTOL, ) npt.assert_allclose( 4.07184261082167, res.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", ).values.min(), rtol=RTOL, ) # check we can also calcluate quantiles quantiles = calculate_quantiles(res, [0.05, 0.17, 0.5, 0.83, 0.95]) npt.assert_allclose( 1.80924238, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", quantile=0.05, ).values, rtol=RTOL, ) npt.assert_allclose( 2.18308358, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp126", quantile=0.95, ).values, rtol=RTOL, ) npt.assert_allclose( 4.08625963, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", quantile=0.05, ).values, rtol=RTOL, ) npt.assert_allclose( 4.76399179, quantiles.filter( variable="Surface Temperature", region="World", year=2100, scenario="ssp370", quantile=0.95, ).values, rtol=RTOL, )