def __call__(self, atmosphere): if self._lapse_cache is not None: return self._lapse_cache T = atmosphere['T'][0, :] p = atmosphere['plev'][:] phlev = atmosphere['phlev'][:] # Use short formula symbols for physical constants. g = constants.earth_standard_gravity L = constants.heat_of_vaporization Rd = constants.specific_gas_constant_dry_air Rv = constants.specific_gas_constant_water_vapor Cp = constants.isobaric_mass_heat_capacity_dry_air gamma_d = g / Cp # dry lapse rate w_saturated = vmr2mixing_ratio(saturation_pressure(T) / p) gamma_m = (gamma_d * ((1 + (L * w_saturated) / (Rd * T)) / (1 + (L**2 * w_saturated) / (Cp * Rv * T**2)) ) ) lapse = interp1d(np.log(p), gamma_m, fill_value='extrapolate')( np.log(phlev[:-1])) if self.fixed: self._lapse_cache = lapse return lapse
def entrain(self, T_con_adiabat, atmosphere): # Physical constants. L = constants.heat_of_vaporization Rv = constants.specific_gas_constant_water_vapor Cp = constants.isobaric_mass_heat_capacity_dry_air # Abbreviated variables references. T_rad = atmosphere["T"][0, :] p = atmosphere["plev"][:] phlev = atmosphere["phlev"][:] # Zero-buoyancy plume entrainment. k_ttl = np.max(np.where(T_con_adiabat >= T_rad)) r_saturated = np.ones_like(p) * 0.0 r_saturated[: k_ttl + 1] = vmr2mixing_ratio( saturation_pressure(T_con_adiabat[: k_ttl + 1]) / p[: k_ttl + 1] ) q_saturated = r_saturated / (1 + r_saturated) q_saturated_hlev = interp1d(np.log(p), q_saturated, fill_value="extrapolate")( np.log(phlev[:-1]) ) z = atmosphere["z"][0, :] zhlev = interp1d(np.log(p), z, fill_value="extrapolate")(np.log(phlev[:-1])) dz_lapse = np.hstack((np.array([z[0] - zhlev[0]]), np.diff(z))) RH = vmr2relative_humidity(atmosphere["H2O"][0, :], p, atmosphere["T"][0, :]) RH = np.where(RH > 1, 1, RH) RH_hlev = interp1d(np.log(p), RH, fill_value="extrapolate")(np.log(phlev[:-1])) entr = self.entr deltaT = np.ones_like(p) * 0.0 k_cb = np.max(np.where(p >= 96000.0)) # First calculate temperature deviation based on Eq. (4) in Singh&O'Gorman (2013) deltaT[k_cb:] = ( 1 / (1 + L / (Rv * T_con_adiabat[k_cb:] ** 2) * L * q_saturated[k_cb:] / Cp) * np.cumsum( entr / zhlev[k_cb:] * (1 - RH_hlev[k_cb:]) * L / Cp * q_saturated_hlev[k_cb:] * dz_lapse[k_cb:] ) ) # Second weight deltaT obtained from above by a height-dependent coefficient, # as described in Eq. (4) in Bao et al. (submitted). if np.any(T_con_adiabat > T_rad): k_ttl = np.max(np.where(T_con_adiabat > T_rad)) z_ttl = z[k_ttl] z_cb = z[k_cb] f = lambda x: x ** (2.0 / 3.0) weight = f((z[k_cb : k_ttl + 1] - z_ttl) / (z_cb - z_ttl)) deltaT[k_cb : k_ttl + 1] = deltaT[k_cb : k_ttl + 1] * weight deltaT[k_ttl + 1 :] = 0 self.create_variable( name="entrainment_cooling", dims=("time", "plev"), data=deltaT.reshape(1, -1), ) return T_con_adiabat - deltaT
def test_vmr2mixing_ratio(self): """Test conversion of VMR to mass mixing ratio.""" w = physics.vmr2mixing_ratio(0.04) assert np.isclose(w, 0.025915747437955664)
#%% PIC 2140 # PIC, it seems HC is actially calculating the specific humidity with his calculation (instead of mixing ratio as he thinks), HOWEVER, it does not make a difference dfPIC2m10min=pd.read_csv('/Volumes/gfi_snowiso/Vapour/2018/processed_data_combined/EG18_level180cm.txt',index_col=0,parse_dates=True,na_values=['NAN']) dfPIC2m10min=dfPIC2m10min.loc[pd.to_datetime('2018-06-11 12:00'):pd.to_datetime('2018-07-01 21:00'),:] #only use specific period where the new 2140 was measuring at 2m only dfPIC2m10min.loc[:,'shum']=dfPIC2m10min.H2O*1e-6*B #you could also use deltatogas function, dfPIC2m.mr is g/kg air --> specific humidity #interpolate to 1h mean dfPIC2m=dfPIC2m10min.resample('1h').mean() # CHECK what typhon does --> Conclusion: What I have done is pretty close to what typhon would do, so no need to change my code again # see what typhon makes from the volume mixing ratio (ppmv) dfPIC2m.loc[:,'ty_mr']=ty.vmr2mixing_ratio(dfPIC2m.H2O*1e-6)*1e3 # to get g/kg dfPIC2m.loc[:,'ty_mr_from_mr']=ty.specific_humidity2mixing_ratio(dfPIC2m.shum/1000)*1000 #assume HC formula is actually for spec humidity and not for mr dfPIC2m.loc[:,'ty_spechum']=ty.vmr2specific_humidity(dfPIC2m.H2O*1e-6)*1e3 # combine to get rid of nan dfcombiPIC=pd.concat([dfPIC2m.shum,geus_h.spechum],axis=1).dropna() # dfcombiPIC dfPIC2m.shum in g/kg and dfgeus.spechum in g/kg #%% calibration of Picarro 2140 EASTGRIP 2019 plt.figure() plt.plot(dfPIC2m10min.shum,label='PIC original',Marker='s',LineStyle='-',color='darkred',MarkerSize=2) plt.plot(dfPIC2m.shum,label='PIC resampled',Marker='*',LineStyle=':',color='blue',MarkerSize=2) plt.plot(geus_h.spechum,label='geus',Marker='s',LineStyle='--',color='orange',MarkerSize=2) plt.legend()