def _calculate_apparent_temperature( temperature: ndarray, wind_speed: ndarray, relative_humidity: ndarray, pressure: ndarray, ) -> ndarray: """ Calculates the apparent temperature from 10 m wind speed, temperature and actual vapour pressure using the linear regression equation for shade described in A Universal Scale of Apparent Temperature, Steadman, 1984, page 1686, table 5. The method used to determine the original values used for the regression equation takes into account many variables which are detailed in Steadman's paper. The paper calculates apparent temperature for wind speeds up to 20 m/s. Here, the apparent temperature regression equation has been used for all wind speeds. This function looks up a value for the saturation vapour pressure of water vapour using the temperature and a table of values. These tabulated values are found using lookup_svp and are corrected to the saturated vapour pressure in air using pressure_correct_svp, both functions are from the WetBulbTemperature plugin which makes use of the Goff-Gratch method. Args: temperature: Temperatures in degrees celsius wind_speed: 10m wind speeds in metres per second relative_humidity: Relative humidities (fractional) pressure: Pressure in Pa Returns: Apparent temperatures in degrees celsius References: Steadman, R. (1984). A Universal Scale of Apparent Temperature. Journal of Climate and Applied Meteorology, 23(12), pp.1674-1687 """ t_kelvin = temperature + 273.15 svp = calculate_svp_in_air(t_kelvin, pressure) avp = 0.001 * svp * relative_humidity apparent_temperature = ( -2.7 + 1.04 * temperature + 2.0 * avp - 0.65 * wind_speed ).astype(np.float32) return apparent_temperature
def test_calculate_svp_in_air(self): """Test pressure-corrected SVP values""" expected = np.array([[0.01362905, 208.47170252, 25187.76423485]]) result = calculate_svp_in_air(self.temperature, self.pressure) np.testing.assert_allclose(result, expected, rtol=1e-5, atol=1e-5)
def process(self, temperature, humidity, pressure, uwind, vwind, topography): """ Calculate precipitation enhancement over orography on high resolution grid. Input diagnostics are all expected to be on the same grid, and are regridded to match the orography. Args: temperature (iris.cube.Cube): Temperature at top of boundary layer humidity (iris.cube.Cube): Relative humidity at top of boundary layer pressure (iris.cube.Cube): Pressure at top of boundary layer uwind (iris.cube.Cube): Positive eastward wind vector component at top of boundary layer vwind (iris.cube.Cube): Positive northward wind vector component at top of boundary layer topography (iris.cube.Cube): Height of topography above sea level on high resolution (1 km) UKPP domain grid Returns: iris.cube.Cube: Precipitation enhancement due to orography in m/s. """ # check input variable cube coordinates match unmatched_coords = compare_coords( [temperature, pressure, humidity, uwind, vwind]) if any(item.keys() for item in unmatched_coords): msg = 'Input cube coordinates {} are unmatched' raise ValueError(msg.format(unmatched_coords)) # check one of the input variable cubes is a 2D spatial field (this is # equivalent to checking all cubes whose coords are matched above) msg = 'Require 2D fields as input; found {} dimensions' if temperature.ndim > 2: raise ValueError(msg.format(temperature.ndim)) check_for_x_and_y_axes(temperature) # check the topography cube is a 2D spatial field if topography.ndim > 2: raise ValueError(msg.format(topography.ndim)) check_for_x_and_y_axes(topography) # regrid variables to match topography and populate class instance self._regrid_and_populate(temperature, humidity, pressure, uwind, vwind, topography) # calculate saturation vapour pressure self.svp = calculate_svp_in_air( self.temperature.data, self.pressure.data) # calculate site-specific orographic enhancement point_orogenh_data = self._point_orogenh() # integrate upstream component grid_coord_km = self.topography.coord(axis='x').copy() grid_coord_km.convert_units('km') self.grid_spacing_km = ( grid_coord_km.points[1] - grid_coord_km.points[0]) orogenh_data = self._add_upstream_component(point_orogenh_data) # create data cubes on the two required output grids orogenh = self._create_output_cube(orogenh_data, temperature) return orogenh
def test_calculate_svp_in_air(self): """Test pressure-corrected SVP values""" expected = np.array([[0.01362905, 208.47170252, 25187.76423485]]) result = calculate_svp_in_air(self.temperature, self.pressure) self.assertArrayAlmostEqual(result, expected)