UFO
Formulas.h
Go to the documentation of this file.
1 /*
2  * (C) Crown copyright 2020, Met Office
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
8 #ifndef UFO_VARIABLETRANSFORMS_FORMULAS_H_
9 #define UFO_VARIABLETRANSFORMS_FORMULAS_H_
10 
11 #include <algorithm>
12 #include <cmath>
13 #include <string>
14 #include <vector>
15 
16 #include "oops/util/DateTime.h"
17 #include "oops/util/Duration.h"
18 #include "oops/util/missingValues.h"
19 #include "ufo/utils/Constants.h"
20 
21 namespace ufo {
22 
23 namespace formulas {
24 
25 /*! Various Methods and Formulations available */
27  // Methods: Met Center
28  UKMO, /*!< UKMO specific formulation */
29  NCAR, /*!< NCAR specific formulation */
30  NOAA, /*!< NOAA specific formulation */
31  DEFAULT, /*!< DEFAULT formulation */
32 
33  // Formulations: Specific authors
38  Rogers
39 };
40 
41 MethodFormulation resolveMethods(const std::string& input);
42 
43 MethodFormulation resolveFormulations(const std::string& input, const std::string& method);
44 
45 // -------------------------------------------------------------------------------------
46 /*!
47 * \brief Calculates saturated vapour pressure from temperature
48 *
49 * \b Formulation \b available:
50 * - UKMO: as Sonntag 1997
51 * - Sonntag:
52 * Calculation is using the Eqn 7 Sonntag (1997)
53 * Reference: "Sonntag, D., Advancements in the field of hygrometry,
54 * Meteorol. Zeitschrift, N. F., 3, 51-66, 1994." .
55 * - Walko:
56 * Polynomial fit of Goff-Gratch (1946) formulation. (Walko, 1991)
57 * - Murphy:
58 * Alternative method to Walko 1991 (costs more CPU, more accurate)
59 * Reference: "Murphy and Koop, Review of the vapour pressure of ice and
60  supercooled water for atmospheric applications, Q. J. R.
61  Meteorol. Soc (2005), 131, pp. 1539-1565."
62 * - NCAR: as default
63 * - NOAA: as default
64 * - DEFAULT:
65 * Classical formula from Rogers and Yau (1989; Eq2.17)
66 *
67 *
68 * \param temp_K
69 * Temperature [k]
70 * \return saturated vapour pressure
71 */
72 float SatVaporPres_fromTemp(const float temp_K,
74 
75 
76 // -------------------------------------------------------------------------------------
77 /*!
78 * \brief Calculates saturated vapour pressure from temperature
79 *
80 * \b Formulation \b available:
81 * - NCAR: as Sonntag 1997
82 * - NOAA: as Sonntag 1997
83 * - UKMO: as Sonntag 1997
84 * - Sonntag:
85 * Correct the the saturation vapour pressure of pure water vapour
86 * using an enhancement factor needed for moist air.
87 * Reference: eg eqns 20, 22 of Sonntag, but for consistency with QSAT the formula
88  below is from eqn A4.6 of Adrian Gill's book.
89 *
90 *
91 * \param e_sub_s
92 * saturation vapour pressure
93 * \param temp_K
94 * temperature [k]
95 * \param pressure
96 * air pressure [Pa]
97 * \return saturated vapour pressure
98 */
99 float SatVaporPres_correction(float e_sub_s, float temp_K, float pressure,
101 // -------------------------------------------------------------------------------------
102 /*!
103 * \brief Calculates Saturated specific humidity or saturated vapour pressure using
104 * saturation vapour pressure.
105 *
106 *
107 * \b Formulation \b available:
108 * - NCAR: as default
109 * - NOAA: as default
110 * - UKMO: as default
111 * - DEFAULT:
112 * Calculation is using the Sonntag (1994) formula. (With fix at low
113 *pressure)
114 *
115 * \param Psat
116 * saturation vapour pressure of pure water vapour
117 * \param P
118 * Pressure
119 * \return Saturated specific humidity or saturated vapour pressure
120 */
121 float Qsat_From_Psat(float Psat, float P,
123 
124 // -------------------------------------------------------------------------------------
125 /*!
126 * \brief Derive Virtual Temperature from saturation vapour pressure, pressure and temperature
127 *
128 * \b Formulation \b available:
129 * - NCAR: as default
130 * - NOAA: as default
131 * - UKMO: as default
132 * - DEFAULT: \f$ Tv = T * ((P + Psat / \epsilon) / (P + Psat)) \f$
133 *
134 * \param Psat
135 * saturation vapour pressure of pure water vapour
136 * \param T
137 * Temperature
138 * \param P
139 * Pressure
140 * \return Virtual Temperature
141 */
142 float VirtualTemp_From_Psat_P_T(float Psat, float P, float T,
144 
145 // -------------------------------------------------------------------------------------
146 /*!
147 * \brief Derive Virtual Tempreture using Relative humidity, sat. vapour pressure, pressure
148 * and temperature
149 *
150 * \b Formulation \b available:
151 * - NCAR: as default
152 * - NOAA: as default
153 * - UKMO: as default
154 * - DEFAULT: \f$ \alpha = Psat * Rh * 0.01 \f$
155 *
156 * \param Rh
157 * Relative humidity
158 * \param Psat
159 * saturation vapour pressure of pure water vapour
160 * \param T
161 * Temperature
162 * \param P
163 * Pressure
164 * \return Virtual Temperature
165 */
166 float VirtualTemp_From_Rh_Psat_P_T(float Rh, float Psat, float P, float T,
168 
169 // -------------------------------------------------------------------------------------
170 /*!
171 * \brief Converts height to pressure using the International Civil Aviation Organization
172 * (ICAO) atmosphere.
173 *
174 * \b Formulation \b available:
175 * - NCAR: as default
176 * - NOAA: as default
177 * - UKMO: as default
178 * - DEFAULT: using ICAO standard
179 *
180 * \param height
181 * observation height in geopotential metres [gpm]
182 * \return pressure
183 */
184 float Height_To_Pressure_ICAO_atmos(float Height,
186 
187 // -------------------------------------------------------------------------------------
188 /*!
189 * \brief Converts pressure to height.
190 *
191 * \b Formulation \b available:
192 * - NCAR: uses a fast approximation for pressures > 120 hPa and the ICAO atmosphere otherwise.
193 * - NOAA: as default
194 * - UKMO: as default
195 * - DEFAULT: uses the ICAO atmosphere for all pressures.
196 *
197 * \param pressure
198 * observation pressure in Pa
199 * \return height in geopotential metres
200 */
201 float Pressure_To_Height(float pressure,
203 
204 // -------------------------------------------------------------------------------------
205 /*!
206 * \brief Converts u and v wind component into wind direction.
207 * Wind direction is defined such that a northerly wind is 0°, an easterly wind is 90°,
208 * a southerly wind is 180°, and a westerly wind is 270°.
209 *
210 * \param u
211 * eastward (u) wind component[m/s]
212 * \param v
213 * northward (v) wind component[m/s]
214 * \return windDirection
215 */
216 float GetWindDirection(float u, float v);
217 
218 // -------------------------------------------------------------------------------------
219 /*!
220 * \brief Converts u and v wind component into wind speed.
221 *
222 * \param u
223 * eastward (u) wind component[m/s]
224 * \param v
225 * northward (v) wind component[m/s]
226 * \return windSpeed
227 */
228 float GetWindSpeed(float u, float v);
229 
230 // -------------------------------------------------------------------------------------
231 /*!
232 * \brief Get eastward (u) wind component from wind speed and direction.
233 *
234 * \param windSpeed
235 * wind speed [m/s]
236 * \param windFromDirection
237 * wind direction [degree]
238 * \return u
239 */
240 float GetWind_U(float windSpeed, float windFromDirection);
241 
242 // -------------------------------------------------------------------------------------
243 /*!
244 * \brief Get northward (v) wind component from wind speed and direction.
245 *
246 * \param windSpeed
247 * wind speed [m/s]
248 * \param windFromDirection
249 * wind direction [degree]
250 * \return v
251 */
252 float GetWind_V(float windSpeed, float windFromDirection);
253 
254 // -------------------------------------------------------------------------------------
255 /*!
256 * \brief Get renumbered scan position 1,2,3,... for satellite instrument
257 * which has been spatially resampled and for which scan position is 2,5,8,...
258 *
259 * \param scanpos
260 * satellite instrument scan position
261 * \return newpos
262 */
263 int RenumberScanPosition(int scanpos);
264 
265 // -------------------------------------------------------------------------------------
266 /*!
267 * \brief Compute horizontal drift latitude, longitude and time for an atmospheric profile.
268 * This formula accepts input and output vectors that correspond to the entire data sample
269 * as well as a vector of the locations of the current profile in the entire sample.
270 * The latter vector is used to select the relevant observations from the entire sample
271 * prior to running the horizontal drift algorithm.
272 * The outputs of the algorithm are placed in the relevant locations in the entire sample.
273 *
274 * \b Formulations \b available:
275 * - DEFAULT:
276 * Calculation is using Eq. 4. of Laroche and Sarrazin (2013).
277 * Reference: "Laroche, S. and Sarrazin, R.,
278 * Impact of Radiosonde Balloon Drift on
279 * Numerical Weather Prediction and Verification,
280 * Weather and Forecasting, 28(3), 772-782, 2013."
281 * - UKMO: as default
282 * - NCAR: as default
283 * - NOAA: as default
284 *
285 * \param locs
286 * Vector of locations of the current profile in the entire data sample.
287 * \param apply
288 * Vector specifying whether a location should be used or not (governed by the where clause).
289 * \param lat_in
290 * Vector of input latitudes in the entire sample [degrees].
291 * \param lon_in
292 * Vector of input longitudes in the entire sample [degrees].
293 * \param time_in
294 * Vector of input datetimes in the entire sample [ISO 8601 format].
295 * \param height
296 * Vector of input heights in the entire sample [m].
297 * \param windspd
298 * Vector of input wind speeds in the entire sample [m/s].
299 * \param winddir
300 * Vector of input wind directions in the entire sample [degrees].
301 * Wind direction is defined such that a northerly wind is 0°, an easterly wind is 90°,
302 * a southerly wind is 180°, and a westerly wind is 270°.
303 * \param [out] lat_out
304 * Vector of output latitudes in the entire sample [degrees].
305 * \param [out] lon_out
306 * Vector of output longitudes in the entire sample [degress].
307 * \param [out] time_out
308 * Vector of output datetimes in the entire sample [ISO 8601 format].
309 * \param formulation
310 * Method used to determine the horizontal drift positions.
311 */
312 void horizontalDrift
313 (const std::vector<size_t> & locs,
314  const std::vector<bool> & apply,
315  const std::vector<float> & lat_in,
316  const std::vector<float> & lon_in,
317  const std::vector<util::DateTime> & time_in,
318  const std::vector<float> & height,
319  const std::vector<float> & windspd,
320  const std::vector<float> & winddir,
321  std::vector<float> & lat_out,
322  std::vector<float> & lon_out,
323  std::vector<util::DateTime> & time_out,
325 
326 } // namespace formulas
327 } // namespace ufo
328 
329 #endif // UFO_VARIABLETRANSFORMS_FORMULAS_H_
float GetWind_U(float windSpeed, float windFromDirection)
Get eastward (u) wind component from wind speed and direction.
Definition: Formulas.cc:347
MethodFormulation resolveFormulations(const std::string &input, const std::string &method)
Definition: Formulas.cc:30
void horizontalDrift(const std::vector< size_t > &locs, const std::vector< bool > &apply, const std::vector< float > &lat_in, const std::vector< float > &lon_in, const std::vector< util::DateTime > &time_in, const std::vector< float > &height, const std::vector< float > &windspd, const std::vector< float > &winddir, std::vector< float > &lat_out, std::vector< float > &lon_out, std::vector< util::DateTime > &time_out, MethodFormulation formulation)
Compute horizontal drift latitude, longitude and time for an atmospheric profile.
Definition: Formulas.cc:381
float Pressure_To_Height(float pressure, MethodFormulation method)
Converts pressure to height.
Definition: Formulas.cc:271
float Qsat_From_Psat(float Psat, float P, MethodFormulation formulation)
Calculates Saturated specific humidity or saturated vapour pressure using saturation vapour pressure.
Definition: Formulas.cc:163
float VirtualTemp_From_Rh_Psat_P_T(float Rh, float Psat, float P, float T, MethodFormulation formulation)
Derive Virtual Tempreture using Relative humidity, sat.
Definition: Formulas.cc:204
float GetWindDirection(float u, float v)
Converts u and v wind component into wind direction.
Definition: Formulas.cc:323
float SatVaporPres_correction(float e_sub_s, float temp_K, float pressure, MethodFormulation formulation)
Calculates saturated vapour pressure from temperature.
Definition: Formulas.cc:132
float VirtualTemp_From_Psat_P_T(float Psat, float P, float T, MethodFormulation formulation)
Derive Virtual Temperature from saturation vapour pressure, pressure and temperature.
Definition: Formulas.cc:187
MethodFormulation resolveMethods(const std::string &input)
Definition: Formulas.cc:22
float SatVaporPres_fromTemp(float temp_K, MethodFormulation formulation)
Calculates saturated vapour pressure from temperature.
Definition: Formulas.cc:45
MethodFormulation
Various Methods and Formulations available.
Definition: Formulas.h:26
@ NCAR
NCAR specific formulation.
Definition: Formulas.h:29
@ DEFAULT
DEFAULT formulation.
Definition: Formulas.h:31
@ LandoltBornstein
Definition: Formulas.h:36
@ NOAA
NOAA specific formulation.
Definition: Formulas.h:30
@ UKMO
UKMO specific formulation.
Definition: Formulas.h:28
int RenumberScanPosition(int scanpos)
Get renumbered scan position 1,2,3,...
Definition: Formulas.cc:372
float Height_To_Pressure_ICAO_atmos(float height, MethodFormulation formulation)
Converts height to pressure using the International Civil Aviation Organization (ICAO) atmosphere.
Definition: Formulas.cc:224
float GetWind_V(float windSpeed, float windFromDirection)
Get northward (v) wind component from wind speed and direction.
Definition: Formulas.cc:359
float GetWindSpeed(float u, float v)
Converts u and v wind component into wind speed.
Definition: Formulas.cc:337
Definition: RunCRTM.h:27