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
« 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.
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 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
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.
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.
97 Returns
98 -------
99 iris.cube.Cube | iris.cube.CubeList
100 Vapour pressure in hPa.
102 Notes
103 -----
104 The vapour pressure can be derived from the relative humidity and
105 temperature based on the following relation
107 .. math:: e = RH * e_s
109 for e the vapour pressure, :math:`e_s` the saturation vapour pressure,
110 and RH the relative humidity.
112 The relative humidity is converted to a decimal. The saturation vapour
113 pressure is calculated using `pressure.vapour_pressure`.
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
134def exner_pressure(
135 pressure: iris.cube.Cube | iris.cube.CubeList,
136) -> iris.cube.Cube | iris.cube.CubeList:
137 r"""Calculate the exner pressure.
139 Arguments
140 ---------
141 pressure: iris.cube.Cube | iris.cube.CubeList
142 Cubes of pressure to be converted.
144 Returns
145 -------
146 iris.cube.Cube | iris.cube.CubeList
147 Exner pressure.
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
157 .. math:: \Pi = \left(\frac{P}{P_0}\right)^{\kappa}
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.
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.
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