Coverage for src/CSET/operators/pressure.py: 100%

41 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-07 15:12 +0000

1# © Crown copyright, Met Office (2022-2026) and CSET contributors. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14 

15"""Operators for pressure conversions.""" 

16 

17import iris.cube 

18import numpy as np 

19 

20from CSET._common import iter_maybe 

21from CSET.operators._atmospheric_constants import E0, KAPPA, P0 

22from CSET.operators.misc import convert_units 

23 

24 

25def vapour_pressure( 

26 temperature: iris.cube.Cube | iris.cube.CubeList, 

27) -> iris.cube.Cube | iris.cube.CubeList: 

28 r"""Calculate the vapour pressure of the atmosphere. 

29 

30 Arguments 

31 --------- 

32 temperature: iris.cube.Cube | iris.cube.CubeList 

33 Cubes of temperature to be converted into vapour pressure. 

34 Temperature must be provided in Kelvin. 

35 

36 Returns 

37 ------- 

38 iris.cube.Cube | iris.cube.CubeList 

39 Vapour pressure in hPa. 

40 

41 Notes 

42 ----- 

43 The vapour pressure represents the pressure exerted by water vapour on the 

44 atmosphere. It is related to atmospheric temperature through the 

45 Clausius-Clapeyron equation. There are several different formulations based 

46 on empirical relations that are used to calculate the vapour pressure. Here, 

47 we calculate the vapour pressure based on [Buck81]_ equation: 

48 

49 .. math:: e = e_0 * exp\left(\frac{17.508 T}{240.97 + T}\right) 

50 

51 for e the vapour pressure, :math:`e_0` the saturation vapour pressure at 

52 a reference temperature of 273.15 K with a value of 6.1121 hPa, and T the 

53 temperature in degrees Celsius. 

54 

55 The temperature is provided in Kelvin and converted to degrees Celsius; 

56 the vapour pressure is returned in hPa. 

57 

58 If the (dry-bulb) temperature is used the value given by the vapour pressure 

59 will be the saturation vapour pressure. On the other hand, if the dewpoint 

60 temperature is used the vapour pressure will be calculated. 

61 

62 Examples 

63 -------- 

64 >>> vapour_pressure = pressure.vapour_pressure(temperature) 

65 """ 

66 v_pressure = iris.cube.CubeList([]) 

67 for T in iter_maybe(temperature): 

68 es = T.copy() 

69 T_units = convert_units(T, "Celsius") 

70 exponent = (17.502 * T_units) / (240.97 + T_units) 

71 es.data = E0 * np.exp(exponent.core_data()) 

72 es.units = "hPa" 

73 es.rename("vapour_pressure") 

74 v_pressure.append(es) 

75 if len(v_pressure) == 1: 

76 return v_pressure[0] 

77 else: 

78 return v_pressure 

79 

80 

81def vapour_pressure_from_relative_humidity( 

82 temperature: iris.cube.Cube | iris.cube.CubeList, 

83 relative_humidity: iris.cube.Cube | iris.cube.CubeList, 

84) -> iris.cube.Cube | iris.cube.CubeList: 

85 r"""Calculate the vapour pressure using relative humidity RH. 

86 

87 Arguments 

88 --------- 

89 temperature: iris.cube.Cube | iris.cube.CubeList 

90 Cubes of temperature to be converted into saturation vapour pressure. 

91 Temperature must be provided in Kelvin. 

92 relative_humidity: iris.cube.Cube | iris.cube.CubeList 

93 Cubes of relative humidity to be converted into vapour pressure. 

94 Relative humidity must be provided in percentage and 

95 will be converted to a decimal by the operator. 

96 

97 Returns 

98 ------- 

99 iris.cube.Cube | iris.cube.CubeList 

100 Vapour pressure in hPa. 

101 

102 Notes 

103 ----- 

104 The vapour pressure can be derived from the relative humidity and 

105 temperature based on the following relation 

106 

107 .. math:: e = RH * e_s 

108 

109 for e the vapour pressure, :math:`e_s` the saturation vapour pressure, 

110 and RH the relative humidity. 

111 

112 The relative humidity is converted to a decimal. The saturation vapour 

113 pressure is calculated using `pressure.vapour_pressure`. 

114 

115 Examples 

116 -------- 

117 >>> vapour_pressure = pressure.vapour_pressure_from_relative_humidity(temperature, relative_humidity) 

118 """ 

119 v_pressure = iris.cube.CubeList([]) 

120 for T, RH in zip( 

121 iter_maybe(temperature), iter_maybe(relative_humidity), strict=True 

122 ): 

123 RH = convert_units(RH, "1") 

124 vp = vapour_pressure(T) * RH 

125 vp.units = "hPa" 

126 vp.rename("vapour_pressure") 

127 v_pressure.append(vp) 

128 if len(v_pressure) == 1: 

129 return v_pressure[0] 

130 else: 

131 return v_pressure 

132 

133 

134def exner_pressure( 

135 pressure: iris.cube.Cube | iris.cube.CubeList, 

136) -> iris.cube.Cube | iris.cube.CubeList: 

137 r"""Calculate the exner pressure. 

138 

139 Arguments 

140 --------- 

141 pressure: iris.cube.Cube | iris.cube.CubeList 

142 Cubes of pressure to be converted. 

143 

144 Returns 

145 ------- 

146 iris.cube.Cube | iris.cube.CubeList 

147 Exner pressure. 

148 

149 Notes 

150 ----- 

151 The Exner pressure is also referred to as the Exner function. It is a 

152 dimensionless parameter that can be used either as a vertical coordinate or 

153 more frequently as a means to simplifying conversions between different 

154 parameters (e.g. Temperature and Potential Temperature; [Holton13]_). 

155 It is calculated as 

156 

157 .. math:: \Pi = \left(\frac{P}{P_0}\right)^{\kappa} 

158 

159 for :math:`\Pi` the Exner Pressure, P the pressure in hPa, :math:`P_0` a reference pressure 

160 of 1000 hPa, :math:`\kappa` the ratio between the specific gas constant of dry air 

161 (287.05 :math:`J kg^{-1} K^{-1}`) and the specific heat capacity at constant pressure 

162 (1005.0 :math:`J kg^{-1} K^{-1}`) equating to 0.28562. 

163 

164 A value below one implies the pressure is higher than the reference pressure; 

165 values above one implies the pressure is lower than the reference pressure; a 

166 value of one implies the pressure is equal to the reference pressure. 

167 

168 Examples 

169 -------- 

170 >>> Exner_pressure = pressure.exner_pressure(pressure) 

171 """ 

172 pi = iris.cube.CubeList([]) 

173 for P in iter_maybe(pressure): 

174 PI = P.copy() 

175 P = convert_units(P, "hPa") 

176 PI.data = (P.core_data() / P0) ** KAPPA 

177 PI.rename("exner_pressure") 

178 PI.units = "1" 

179 pi.append(PI) 

180 if len(pi) == 1: 

181 return pi[0] 

182 else: 

183 return pi