Coverage for src / CSET / operators / pressure.py: 100%
41 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-28 09:58 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-28 09:58 +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.
15"""Operators for pressure conversions."""
17import iris.cube
18import numpy as np
20from CSET._common import iter_maybe
21from CSET.operators._atmospheric_constants import E0, KAPPA, P0
22from CSET.operators.misc import convert_units
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.
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.
36 Returns
37 -------
38 iris.cube.Cube | iris.cube.CubeList
39 Vapour pressure in hPa.
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:
49 .. math:: e = e_0 * exp\left(\frac{17.508 T}{240.97 + T}\right)
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.
55 The temperature is provided in Kelvin and converted to degrees Celsius;
56 the vapour pressure is returned in hPa.
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.
62 References
63 ----------
64 .. [Buck81] Buck, A.L. (1981) "New Equations for Computing Vapor Pressure
65 and Enhancement Factor". J. App. Meteor. Clim. 20: 1527-1532.
67 Examples
68 --------
69 >>> vapour_pressure = pressure.vapour_pressure(temperature)
70 """
71 v_pressure = iris.cube.CubeList([])
72 for T in iter_maybe(temperature):
73 es = T.copy()
74 T_units = convert_units(T, "Celsius")
75 exponent = (17.502 * T_units) / (240.97 + T_units)
76 es.data = E0 * np.exp(exponent.core_data())
77 es.units = "hPa"
78 es.rename("vapour_pressure")
79 v_pressure.append(es)
80 if len(v_pressure) == 1:
81 return v_pressure[0]
82 else:
83 return v_pressure
86def vapour_pressure_from_relative_humidity(
87 temperature: iris.cube.Cube | iris.cube.CubeList,
88 relative_humidity: iris.cube.Cube | iris.cube.CubeList,
89) -> iris.cube.Cube | iris.cube.CubeList:
90 r"""Calculate the vapour pressure using relative humidity RH.
92 Arguments
93 ---------
94 temperature: iris.cube.Cube | iris.cube.CubeList
95 Cubes of temperature to be converted into saturation vapour pressure.
96 Temperature must be provided in Kelvin.
97 relative_humidity: iris.cube.Cube | iris.cube.CubeList
98 Cubes of relative humidity to be converted into vapour pressure.
99 Relative humidity must be provided in percentage and
100 will be converted to a decimal by the operator.
102 Returns
103 -------
104 iris.cube.Cube | iris.cube.CubeList
105 Vapour pressure in hPa.
107 Notes
108 -----
109 The vapour pressure can be derived from the relative humidity and
110 temperature based on the following relation
112 .. math:: e = RH * e_s
114 for e the vapour pressure, :math:`e_s` the saturation vapour pressure,
115 and RH the relative humidity.
117 The relative humidity is converted to a decimal. The saturation vapour
118 pressure is calculated using `pressure.vapour_pressure`.
120 Examples
121 --------
122 >>> vapour_pressure = pressure.vapour_pressure_from_relative_humidity(temperature, relative_humidity)
123 """
124 v_pressure = iris.cube.CubeList([])
125 for T, RH in zip(
126 iter_maybe(temperature), iter_maybe(relative_humidity), strict=True
127 ):
128 RH = convert_units(RH, "1")
129 vp = vapour_pressure(T) * RH
130 vp.units = "hPa"
131 vp.rename("vapour_pressure")
132 v_pressure.append(vp)
133 if len(v_pressure) == 1:
134 return v_pressure[0]
135 else:
136 return v_pressure
139def exner_pressure(
140 pressure: iris.cube.Cube | iris.cube.CubeList,
141) -> iris.cube.Cube | iris.cube.CubeList:
142 r"""Calculate the exner pressure.
144 Arguments
145 ---------
146 pressure: iris.cube.Cube | iris.cube.CubeList
147 Cubes of pressure to be converted.
149 Returns
150 -------
151 iris.cube.Cube | iris.cube.CubeList
152 Exner pressure.
154 Notes
155 -----
156 The Exner pressure is also referred to as the Exner function. It is a
157 dimensionless parameter that can be used either as a vertical coordinate or
158 more frequently as a means to simplifying conversions between different
159 parameters (e.g. Temperature and Potential Temperature; [Holton13]_).
160 It is calculated as
162 .. math:: \Pi = \left(\frac{P}{P_0}\right)^{\kappa}
164 for :math:`\Pi` the Exner Pressure, P the pressure in hPa, :math:`P_0` a reference pressure
165 of 1000 hPa, :math:`\kappa` the ratio between the specific gas constant of dry air
166 (287.05 :math:`J kg^{-1} K^{-1}`) and the specific heat capacity at constant pressure
167 (1005.0 :math:`J kg^{-1} K^{-1}`) equating to 0.28562.
169 A value below one implies the pressure is higher than the reference pressure;
170 values above one implies the pressure is lower than the reference pressure; a
171 value of one implies the pressure is equal to the reference pressure.
173 References
174 ----------
175 .. [Holton13] Holton, J.R. and Hakim G.J. (2013) "An Introduction to Dynamic
176 Meteorology." 5th Edition, Burlington, MA, Elsevier Academic Press, 532 pp.
178 Examples
179 --------
180 >>> Exner_pressure = pressure.exner_pressure(pressure)
181 """
182 pi = iris.cube.CubeList([])
183 for P in iter_maybe(pressure):
184 PI = P.copy()
185 P = convert_units(P, "hPa")
186 PI.data = (P.core_data() / P0) ** KAPPA
187 PI.rename("exner_pressure")
188 PI.units = "1"
189 pi.append(PI)
190 if len(pi) == 1:
191 return pi[0]
192 else:
193 return pi