def test_twolayer_defaults( update_expected_files, test_rcmip_forcings_scmrun, test_twolayer_output_dir, run_model_output_comparison, ): twolayer_default = TwoLayerModel() res = twolayer_default.run_scenarios(test_rcmip_forcings_scmrun) expected = os.path.join(test_twolayer_output_dir, "test_twolayer_defaults.csv") run_model_output_comparison(res, expected, update_expected_files)
def test_twolayer_plus_efficacy( update_expected_files, test_rcmip_forcings_scmrun, test_twolayer_output_dir, run_model_output_comparison, ): twolayer_plus_efficacy = TwoLayerModel(efficacy=1.2 * ur("dimensionless")) res = twolayer_plus_efficacy.run_scenarios(test_rcmip_forcings_scmrun) expected = os.path.join(test_twolayer_output_dir, "test_twolayer_plus_efficacy.csv") run_model_output_comparison(res, expected, update_expected_files)
def test_twolayer_plus_state_dependence( update_expected_files, test_rcmip_forcings_scmrun, test_twolayer_output_dir, run_model_output_comparison, ): twolayer_plus_state_dependence = TwoLayerModel(a=0.05 * ur("W/m^2/delta_degC^2")) res = twolayer_plus_state_dependence.run_scenarios(test_rcmip_forcings_scmrun) expected = os.path.join( test_twolayer_output_dir, "test_twolayer_plus_state_dependence.csv" ) run_model_output_comparison(res, expected, update_expected_files)
def test_get_two_layer_model_parameters(self, check_equal_pint): tq1 = 0.3 * ur("delta_degC/(W/m^2)") tq2 = 0.4 * ur("delta_degC/(W/m^2)") td1 = 3 * ur("yr") td2 = 300.0 * ur("yr") tefficacy = 1.2 * ur("dimensionless") start_paras = dict( d1=td1, d2=td2, q1=tq1, q2=tq2, efficacy=tefficacy, ) mod_instance = self.tmodel(**start_paras) # for explanation of what is going on, see # impulse-response-equivalence.ipynb efficacy = tefficacy lambda0 = 1 / (tq1 + tq2) C = (td1 * td2) / (tq1 * td2 + tq2 * td1) a1 = lambda0 * tq1 a2 = lambda0 * tq2 tau1 = td1 tau2 = td2 C_D = (lambda0 * (tau1 * a1 + tau2 * a2) - C) / efficacy eta = C_D / (tau1 * a2 + tau2 * a1) expected = { "lambda0": lambda0, "du": C / (DENSITY_WATER * HEAT_CAPACITY_WATER), "dl": C_D / (DENSITY_WATER * HEAT_CAPACITY_WATER), "eta": eta, "efficacy": efficacy, } res = mod_instance.get_two_layer_parameters() assert res == expected # check circularity circular_params = TwoLayerModel( **res).get_impulse_response_parameters() for k, v in circular_params.items(): check_equal_pint(v, start_paras[k])
def test_two_layer_impulse_response_equivalence(two_layer_config): time = np.arange(1750, 2501) forcing = 0.3 * np.sin(time / 15 * 2 * np.pi) + 3.0 * time / time.max() inp = ScmRun( data=forcing, index=time, columns={ "scenario": "test_scenario", "model": "unspecified", "climate_model": "junk input", "variable": "Effective Radiative Forcing", "unit": "W/m^2", "region": "World", }, ) twolayer = TwoLayerModel(**two_layer_config) res_twolayer = twolayer.run_scenarios(inp) impulse_response = ImpulseResponseModel( **twolayer.get_impulse_response_parameters()) res_impulse_response = impulse_response.run_scenarios(inp) assert (res_twolayer["time"] == res_impulse_response["time"]).all() npt.assert_allclose( res_twolayer.filter(variable="Effective Radiative Forcing").values, res_impulse_response.filter( variable="Effective Radiative Forcing").values, ) npt.assert_allclose( res_twolayer.filter(variable="Heat Uptake").values, res_impulse_response.filter(variable="Heat Uptake").values, atol=0.1, # numerical errors? ) npt.assert_allclose( res_twolayer.filter(variable="Surface Temperature|Upper").values, res_impulse_response.filter(variable="Surface Temperature").values, atol=0.1, # numerical errors? )
def test_calculate_next_rndt(self, check_same_unit): ttemp1 = 1.1 ttemp_2 = 0.6 tq1 = 0.5 tq2 = 0.3 td1 = 30 td2 = 600 terf = 1.2 tefficacy = 1.13 helper = self.tmodel( q1=tq1 * ur("delta_degC/(W/m^2)"), q2=tq2 * ur("delta_degC/(W/m^2)"), d1=td1 * ur("yr"), d2=td2 * ur("yr"), efficacy=tefficacy * ur("dimensionless"), ) helper_twolayer = TwoLayerModel(**helper.get_two_layer_parameters()) gh = _calculate_geoffroy_helper_parameters( helper_twolayer.du, helper_twolayer.dl, helper_twolayer.lambda0, helper_twolayer.efficacy, helper_twolayer.eta, ) # see notebook for discussion of why this is so efficacy_term = (helper_twolayer.eta * (helper_twolayer.efficacy - 1) * (((1 - gh["phi1"]) * ttemp1 * ur("delta_degC")) + ((1 - gh["phi2"]) * ttemp_2 * ur("delta_degC")))) expected = (terf * ur(helper._erf_unit) - ((ttemp1 + ttemp_2) * ur(helper._temp1_unit)) * helper_twolayer.lambda0 - efficacy_term) assert str(expected.units) == "watt / meter ** 2" res = helper._calculate_next_rndt(ttemp1, ttemp_2, terf, tefficacy) npt.assert_allclose(res, expected.magnitude) # check internal units make sense check_same_unit(self.tmodel._q1_unit, self.tmodel._q2_unit) check_same_unit(helper_twolayer._lambda0_unit, (1.0 * ur(self.tmodel._q2_unit)**-1)) check_same_unit( self.tmodel._erf_unit, ((1.0 * ur(self.tmodel._temp1_unit) / (1.0 * ur(self.tmodel._q1_unit))).units), ) check_same_unit( self.tmodel._erf_unit, efficacy_term.units, )