Source code for improver.generate_ancillaries.generate_svp_table
# (C) Crown Copyright, Met Office. All rights reserved.
#
# This file is part of 'IMPROVER' and is released under the BSD 3-Clause license.
# See LICENSE in the root of the repository for full licensing details.
"""A module for creating a saturated vapour pressure table"""
import warnings
import iris
import numpy as np
from iris.cube import Cube
from numpy import ndarray
from improver import BasePlugin
from improver.constants import TRIPLE_PT_WATER
[docs]
class SaturatedVapourPressureTable(BasePlugin):
"""
Plugin to create a saturated vapour pressure lookup table.
"""
MAX_VALID_TEMPERATURE = 373.0
MIN_VALID_TEMPERATURE = 173.0
[docs]
def __init__(
self, t_min: float = 183.15, t_max: float = 338.25, t_increment: float = 0.1
) -> None:
"""
Create a table of saturated vapour pressures that can be interpolated
through to obtain an SVP value for any temperature within the range
t_min --> (t_max - t_increment).
The default min/max values create a table that provides SVP values
covering the temperature range -90C to +65.1C. Note that the last
bin is not used, so the SVP value corresponding to +65C is the highest
that will be used.
Args:
t_min:
The minimum temperature for the range, in Kelvin.
t_max:
The maximum temperature for the range, in Kelvin.
t_increment:
The temperature increment at which to create values for the
saturated vapour pressure between t_min and t_max.
"""
self.t_min = t_min
self.t_max = t_max
self.t_increment = t_increment
def __repr__(self) -> str:
"""Represent the configured plugin instance as a string."""
result = (
"<SaturatedVapourPressureTable: t_min: {}; t_max: {}; "
"t_increment: {}>".format(self.t_min, self.t_max, self.t_increment)
)
return result
[docs]
def saturation_vapour_pressure_goff_gratch(self, temperature: ndarray) -> ndarray:
"""
Saturation Vapour pressure in a water vapour system calculated using
the Goff-Gratch Equation (WMO standard method).
Args:
temperature:
Temperature values in Kelvin. Valid from 173K to 373K
Returns:
Corresponding values of saturation vapour pressure for a pure
water vapour system, in hPa.
References:
Numerical data and functional relationships in science and
technology. New series. Group V. Volume 4. Meteorology.
Subvolume b. Physical and chemical properties of the air, P35.
"""
constants = {
1: 10.79574,
2: 5.028,
3: 1.50475e-4,
4: -8.2969,
5: 0.42873e-3,
6: 4.76955,
7: 0.78614,
8: -9.09685,
9: 3.56654,
10: 0.87682,
11: 0.78614,
}
# Make float64 for calculations below.
triple_pt = np.float64(TRIPLE_PT_WATER)
# Values for which method is considered valid (see reference).
# WetBulbTemperature.check_range(temperature.data, 173., 373.)
if (
temperature.max() > self.MAX_VALID_TEMPERATURE
or temperature.min() < self.MIN_VALID_TEMPERATURE
):
msg = "Temperatures out of SVP table range: min {}, max {}"
warnings.warn(msg.format(temperature.min(), temperature.max()))
svp = temperature.copy()
for cell in np.nditer(svp, op_flags=["readwrite"]):
if cell > triple_pt:
n0 = constants[1] * (1.0 - triple_pt / cell)
n1 = constants[2] * np.log10(cell / triple_pt)
n2 = constants[3] * (
1.0 - np.power(10.0, (constants[4] * (cell / triple_pt - 1.0)))
)
n3 = constants[5] * (
np.power(10.0, (constants[6] * (1.0 - triple_pt / cell))) - 1.0
)
log_es = n0 - n1 + n2 + n3 + constants[7]
cell[...] = np.power(10.0, log_es)
else:
n0 = constants[8] * ((triple_pt / cell) - 1.0)
n1 = constants[9] * np.log10(triple_pt / cell)
n2 = constants[10] * (1.0 - (cell / triple_pt))
log_es = n0 - n1 + n2 + constants[11]
cell[...] = np.power(10.0, log_es)
return svp
[docs]
def process(self) -> Cube:
"""
Create a lookup table of saturation vapour pressure in a pure water
vapour system for the range of required temperatures.
Returns:
A cube of saturated vapour pressure values at temperature
points defined by t_min, t_max, and t_increment (defined above).
"""
temperatures = np.arange(
self.t_min, self.t_max + 0.5 * self.t_increment, self.t_increment
)
svp_data = self.saturation_vapour_pressure_goff_gratch(temperatures)
temperature_coord = iris.coords.DimCoord(
temperatures, "air_temperature", units="K"
)
# Output of the Goff-Gratch is in hPa, but we want to return in Pa.
svp = iris.cube.Cube(
svp_data,
long_name="saturated_vapour_pressure",
units="hPa",
dim_coords_and_dims=[(temperature_coord, 0)],
)
svp.convert_units("Pa")
svp.attributes["minimum_temperature"] = self.t_min
svp.attributes["maximum_temperature"] = self.t_max
svp.attributes["temperature_increment"] = self.t_increment
return svp