Completed
Pull Request — master (#473)
by
unknown
54s
created

test_most_unstable_parcel()   A

Complexity

Conditions 1

Size

Total Lines 9

Duplication

Lines 9
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 9
loc 9
rs 9.6666
1
# Copyright (c) 2008-2015 MetPy Developers.
2
# Distributed under the terms of the BSD 3-Clause License.
3
# SPDX-License-Identifier: BSD-3-Clause
4
"""Test the `thermo` module."""
5
6
import numpy as np
7
import pytest
8
9
from metpy.calc import (density, dewpoint, dewpoint_rh, dry_lapse, el,
10
                        equivalent_potential_temperature, get_layer, lcl, lfc, mixing_ratio,
11
                        mixing_ratio_from_specific_humidity, moist_lapse,
12
                        most_unstable_parcel, parcel_profile, potential_temperature,
13
                        psychrometric_vapor_pressure_wet,
14
                        relative_humidity_from_mixing_ratio,
15
                        relative_humidity_from_specific_humidity,
16
                        relative_humidity_wet_psychrometric,
17
                        saturation_mixing_ratio,
18
                        saturation_vapor_pressure, vapor_pressure,
19
                        virtual_potential_temperature, virtual_temperature)
20
21
from metpy.testing import assert_almost_equal, assert_array_almost_equal, assert_nan
22
from metpy.units import units
23
24
25
def test_potential_temperature():
26
    """Test potential_temperature calculation."""
27
    temp = np.array([278., 283., 291., 298.]) * units.kelvin
28
    pres = np.array([900., 500., 300., 100.]) * units.mbar
29
    real_th = np.array([286.493, 344.961, 410.4335, 575.236]) * units.kelvin
30
    assert_array_almost_equal(potential_temperature(pres, temp), real_th, 3)
31
32
33
def test_scalar():
34
    """Test potential_temperature accepts scalar values."""
35
    assert_almost_equal(potential_temperature(1000. * units.mbar, 293. * units.kelvin),
36
                        293. * units.kelvin, 4)
37
    assert_almost_equal(potential_temperature(800. * units.mbar, 293. * units.kelvin),
38
                        312.2828 * units.kelvin, 4)
39
40
41
def test_fahrenheit():
42
    """Test that potential_temperature handles temperature values in Fahrenheit."""
43
    assert_almost_equal(potential_temperature(800. * units.mbar, 68. * units.degF),
44
                        (312.444 * units.kelvin).to(units.degF), 2)
45
46
47
def test_pot_temp_inhg():
48
    """Test that potential_temperature can handle pressure not in mb (issue #165)."""
49
    assert_almost_equal(potential_temperature(29.92 * units.inHg, 29 * units.degC),
50
                        301.019735 * units.kelvin, 4)
51
52
53
def test_dry_lapse():
54
    """Test dry_lapse calculation."""
55
    levels = np.array([1000, 900, 864.89]) * units.mbar
56
    temps = dry_lapse(levels, 303.15 * units.kelvin)
57
    assert_array_almost_equal(temps,
58
                              np.array([303.15, 294.16, 290.83]) * units.kelvin, 2)
59
60
61
def test_dry_lapse_2_levels():
62
    """Test dry_lapse calculation when given only two levels."""
63
    temps = dry_lapse(np.array([1000., 500.]) * units.mbar, 293. * units.kelvin)
64
    assert_array_almost_equal(temps, [293., 240.3723] * units.kelvin, 4)
65
66
67
def test_moist_lapse():
68
    """Test moist_lapse calculation."""
69
    temp = moist_lapse(np.array([1000., 800., 600., 500., 400.]) * units.mbar,
70
                       293. * units.kelvin)
71
    true_temp = np.array([293, 284.64, 272.81, 264.42, 252.91]) * units.kelvin
72
    assert_array_almost_equal(temp, true_temp, 2)
73
74
75
def test_moist_lapse_degc():
76
    """Test moist_lapse with Celsius temperatures."""
77
    temp = moist_lapse(np.array([1000., 800., 600., 500., 400.]) * units.mbar,
78
                       19.85 * units.degC)
79
    true_temp = np.array([293, 284.64, 272.81, 264.42, 252.91]) * units.kelvin
80
    assert_array_almost_equal(temp, true_temp, 2)
81
82
83
def test_parcel_profile():
84
    """Test parcel profile calculation."""
85
    levels = np.array([1000., 900., 800., 700., 600., 500., 400.]) * units.mbar
86
    true_prof = np.array([303.15, 294.16, 288.026, 283.073, 277.058, 269.402,
87
                          258.966]) * units.kelvin
88
89
    prof = parcel_profile(levels, 30. * units.degC, 20. * units.degC)
90
    assert_array_almost_equal(prof, true_prof, 2)
91
92
93
def test_parcel_profile_saturated():
94
    """Test parcel_profile works when LCL in levels (issue #232)."""
95
    levels = np.array([1000., 700., 500.]) * units.mbar
96
    true_prof = np.array([296.95, 284.381, 271.123]) * units.kelvin
97
98
    prof = parcel_profile(levels, 23.8 * units.degC, 23.8 * units.degC)
99
    assert_array_almost_equal(prof, true_prof, 2)
100
101
102
def test_sat_vapor_pressure():
103
    """Test saturation_vapor_pressure calculation."""
104
    temp = np.array([5., 10., 18., 25.]) * units.degC
105
    real_es = np.array([8.72, 12.27, 20.63, 31.67]) * units.mbar
106
    assert_array_almost_equal(saturation_vapor_pressure(temp), real_es, 2)
107
108
109
def test_sat_vapor_pressure_scalar():
110
    """Test saturation_vapor_pressure handles scalar values."""
111
    es = saturation_vapor_pressure(0 * units.degC)
112
    assert_almost_equal(es, 6.112 * units.mbar, 3)
113
114
115
def test_sat_vapor_pressure_fahrenheit():
116
    """Test saturation_vapor_pressure handles temperature in Fahrenheit."""
117
    temp = np.array([50., 68.]) * units.degF
118
    real_es = np.array([12.2717, 23.3695]) * units.mbar
119
    assert_array_almost_equal(saturation_vapor_pressure(temp), real_es, 4)
120
121
122
def test_basic_dewpoint_rh():
123
    """Test dewpoint_rh function."""
124
    temp = np.array([30., 25., 10., 20., 25.]) * units.degC
125
    rh = np.array([30., 45., 55., 80., 85.]) / 100.
126
127
    real_td = np.array([11, 12, 1, 16, 22]) * units.degC
128
    assert_array_almost_equal(real_td, dewpoint_rh(temp, rh), 0)
129
130
131
def test_scalar_dewpoint_rh():
132
    """Test dewpoint_rh with scalar values."""
133
    td = dewpoint_rh(10.6 * units.degC, 0.37)
134
    assert_almost_equal(td, 26. * units.degF, 0)
135
136
137
def test_dewpoint():
138
    """Test dewpoint calculation."""
139
    assert_almost_equal(dewpoint(6.112 * units.mbar), 0. * units.degC, 2)
140
141
142
def test_dewpoint_weird_units():
143
    """Test dewpoint using non-standard units.
144
145
    Revealed from odd dimensionless units and ending up using numpy.ma math
146
    functions instead of numpy ones.
147
    """
148
    assert_almost_equal(dewpoint(15825.6 * units('g * mbar / kg')),
149
                        13.8564 * units.degC, 4)
150
151
152
def test_mixing_ratio():
153
    """Test mixing ratio calculation."""
154
    p = 998. * units.mbar
155
    e = 73.75 * units.mbar
156
    assert_almost_equal(mixing_ratio(e, p), 0.04963, 2)
157
158
159
def test_vapor_pressure():
160
    """Test vapor pressure calculation."""
161
    assert_almost_equal(vapor_pressure(998. * units.mbar, 0.04963),
162
                        73.74925 * units.mbar, 5)
163
164
165
def test_lcl():
166
    """Test LCL calculation."""
167
    lcl_pressure, lcl_temperature = lcl(1000. * units.mbar, 30. * units.degC, 20. * units.degC)
168
    assert_almost_equal(lcl_pressure, 864.761 * units.mbar, 2)
169
    assert_almost_equal(lcl_temperature, 17.676 * units.degC, 2)
170
171
172
def test_lcl_convergence():
173
    """Test LCL calculation convergence failure."""
174
    with pytest.raises(RuntimeError):
175
        lcl(1000. * units.mbar, 30. * units.degC, 20. * units.degC, max_iters=2)
176
177
178 View Code Duplication
def test_lfc_basic():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
179
    """Test LFC calculation."""
180
    levels = np.array([959., 779.2, 751.3, 724.3, 700., 269.]) * units.mbar
181
    temperatures = np.array([22.2, 14.6, 12., 9.4, 7., -49.]) * units.celsius
182
    dewpoints = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
183
    l = lfc(levels, temperatures, dewpoints)
184
    assert_almost_equal(l[0], 727.468 * units.mbar, 2)
185
    assert_almost_equal(l[1], 9.705 * units.celsius, 2)
186
187
188
def test_no_lfc():
189
    """Test LFC calculation when there is no LFC in the data."""
190
    levels = np.array([959., 867.9, 779.2, 647.5, 472.5, 321.9, 251.]) * units.mbar
191
    temperatures = np.array([22.2, 17.4, 14.6, 1.4, -17.6, -39.4, -52.5]) * units.celsius
192
    dewpoints = np.array([9., 4.3, -21.2, -26.7, -31., -53.3, -66.7]) * units.celsius
193
    lfc_pressure, lfc_temperature = lfc(levels, temperatures, dewpoints)
194
    assert assert_nan(lfc_pressure, levels.units)
195
    assert assert_nan(lfc_temperature, temperatures.units)
196
197
198 View Code Duplication
def test_lfc_inversion():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
199
    """Test LFC when there is an inversion to be sure we don't pick that."""
200
    levels = np.array([963., 789., 782.3, 754.8, 728.1, 727., 700.,
201
                       571., 450., 300., 248.]) * units.mbar
202
    temperatures = np.array([25.4, 18.4, 17.8, 15.4, 12.9, 12.8,
203
                             10., -3.9, -16.3, -41.1, -51.5]) * units.celsius
204
    dewpoints = np.array([20.4, 0.4, -0.5, -4.3, -8., -8.2, -9.,
205
                          -23.9, -33.3, -54.1, -63.5]) * units.celsius
206
    l = lfc(levels, temperatures, dewpoints)
207
    assert_almost_equal(l[0], 706.0103 * units.mbar, 2)
208
    assert_almost_equal(l[1], 10.6232 * units.celsius, 2)
209
210
211 View Code Duplication
def test_lfc_equals_lcl():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
212
    """Test LFC when there is no cap and the lfc is equal to the lcl."""
213
    levels = np.array([912., 905.3, 874.4, 850., 815.1, 786.6, 759.1,
214
                       748., 732.2, 700., 654.8]) * units.mbar
215
    temperatures = np.array([29.4, 28.7, 25.2, 22.4, 19.4, 16.8,
216
                             14.3, 13.2, 12.6, 11.4, 7.1]) * units.celsius
217
    dewpoints = np.array([18.4, 18.1, 16.6, 15.4, 13.2, 11.4, 9.6,
218
                          8.8, 0., -18.6, -22.9]) * units.celsius
219
    l = lfc(levels, temperatures, dewpoints)
220
    assert_almost_equal(l[0], 777.0333 * units.mbar, 2)
221
    assert_almost_equal(l[1], 15.8714 * units.celsius, 2)
222
223
224
def test_saturation_mixing_ratio():
225
    """Test saturation mixing ratio calculation."""
226
    p = 999. * units.mbar
227
    t = 288. * units.kelvin
228
    assert_almost_equal(saturation_mixing_ratio(p, t), .01068, 3)
229
230
231
def test_equivalent_potential_temperature():
232
    """Test equivalent potential temperature calculation."""
233
    p = 999. * units.mbar
234
    t = 288. * units.kelvin
235
    ept = equivalent_potential_temperature(p, t)
236
    assert_almost_equal(ept, 315.9548 * units.kelvin, 3)
237
238
239
def test_virtual_temperature():
240
    """Test virtual temperature calculation."""
241
    t = 288. * units.kelvin
242
    qv = .0016  # kg/kg
243
    tv = virtual_temperature(t, qv)
244
    assert_almost_equal(tv, 288.2796 * units.kelvin, 3)
245
246
247
def test_virtual_potential_temperature():
248
    """Test virtual potential temperature calculation."""
249
    p = 999. * units.mbar
250
    t = 288. * units.kelvin
251
    qv = .0016  # kg/kg
252
    theta_v = virtual_potential_temperature(p, t, qv)
253
    assert_almost_equal(theta_v, 288.3620 * units.kelvin, 3)
254
255
256
def test_density():
257
    """Test density calculation."""
258
    p = 999. * units.mbar
259
    t = 288. * units.kelvin
260
    qv = .0016  # kg/kg
261
    rho = density(p, t, qv).to(units.kilogram / units.meter ** 3)
262
    assert_almost_equal(rho, 1.2072 * (units.kilogram / units.meter ** 3), 3)
263
264
265
def test_el():
266
    """Test equilibrium layer calculation."""
267
    levels = np.array([959., 779.2, 751.3, 724.3, 700., 269.]) * units.mbar
268
    temperatures = np.array([22.2, 14.6, 12., 9.4, 7., -38.]) * units.celsius
269
    dewpoints = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
270
    el_pressure, el_temperature = el(levels, temperatures, dewpoints)
271
    assert_almost_equal(el_pressure, 520.8700 * units.mbar, 3)
272
    assert_almost_equal(el_temperature, -11.7027 * units.degC, 3)
273
274
275
def test_no_el():
276
    """Test equilibrium layer calculation when there is no EL in the data."""
277
    levels = np.array([959., 867.9, 779.2, 647.5, 472.5, 321.9, 251.]) * units.mbar
278
    temperatures = np.array([22.2, 17.4, 14.6, 1.4, -17.6, -39.4, -52.5]) * units.celsius
279
    dewpoints = np.array([19., 14.3, -11.2, -16.7, -21., -43.3, -56.7]) * units.celsius
280
    el_pressure, el_temperature = el(levels, temperatures, dewpoints)
281
    assert assert_nan(el_pressure, levels.units)
282
    assert assert_nan(el_temperature, temperatures.units)
283
284
285
def test_el_lfc_equals_lcl():
286
    """Test equilibrium layer calculation when the lfc equals the lcl."""
287
    levels = np.array([912., 905.3, 874.4, 850., 815.1, 786.6, 759.1, 748.,
288
                       732.3, 700., 654.8, 606.8, 562.4, 501.8, 500., 482.,
289
                       400., 393.3, 317.1, 307., 300., 252.7, 250., 200.,
290
                       199.3, 197., 190., 172., 156.6, 150., 122.9, 112.,
291
                       106.2, 100.]) * units.mbar
292
    temperatures = np.array([29.4, 28.7, 25.2, 22.4, 19.4, 16.8, 14.3,
293
                             13.2, 12.6, 11.4, 7.1, 2.2, -2.7, -10.1,
294
                             -10.3, -12.4, -23.3, -24.4, -38., -40.1, -41.1,
295
                             -49.8, -50.3, -59.1, -59.1, -59.3, -59.7, -56.3,
296
                             -56.9, -57.1, -59.1, -60.1, -58.6, -56.9]) * units.celsius
297
    dewpoints = np.array([18.4, 18.1, 16.6, 15.4, 13.2, 11.4, 9.6, 8.8, 0.,
298
                          -18.6, -22.9, -27.8, -32.7, -40.1, -40.3, -42.4, -53.3,
299
                          -54.4, -68., -70.1, -70., -70., -70., -70., -70., -70.,
300
                          -70., -70., -70., -70., -70., -70., -70., -70.]) * units.celsius
301
    el_pressure, el_temperature = el(levels, temperatures, dewpoints)
302
    assert_almost_equal(el_pressure, 175.8684 * units.mbar, 3)
303
    assert_almost_equal(el_temperature, -57.0307 * units.degC, 3)
304
305
306
def test_wet_psychrometric_vapor_pressure():
307
    """Test calculation of vapor pressure from wet and dry bulb temperatures."""
308
    p = 1013.25 * units.mbar
309
    dry_bulb_temperature = 20. * units.degC
310
    wet_bulb_temperature = 18. * units.degC
311
    psychrometric_vapor_pressure = psychrometric_vapor_pressure_wet(dry_bulb_temperature,
312
                                                                    wet_bulb_temperature, p)
313
    assert_almost_equal(psychrometric_vapor_pressure, 19.3673 * units.mbar, 3)
314
315
316
def test_wet_psychrometric_rh():
317
    """Test calculation of relative humidity from wet and dry bulb temperatures."""
318
    p = 1013.25 * units.mbar
319
    dry_bulb_temperature = 20. * units.degC
320
    wet_bulb_temperature = 18. * units.degC
321
    psychrometric_rh = relative_humidity_wet_psychrometric(dry_bulb_temperature,
322
                                                           wet_bulb_temperature, p)
323
    assert_almost_equal(psychrometric_rh, 82.8747 * units.percent, 3)
324
325
326
def test_wet_psychrometric_rh_kwargs():
327
    """Test calculation of relative humidity from wet and dry bulb temperatures."""
328
    p = 1013.25 * units.mbar
329
    dry_bulb_temperature = 20. * units.degC
330
    wet_bulb_temperature = 18. * units.degC
331
    coeff = 6.1e-4 / units.kelvin
332
    psychrometric_rh = relative_humidity_wet_psychrometric(dry_bulb_temperature,
333
                                                           wet_bulb_temperature, p,
334
                                                           psychrometer_coefficient=coeff)
335
    assert_almost_equal(psychrometric_rh, 82.9701 * units.percent, 3)
336
337
338
def test_rh_mixing_ratio():
339
    """Tests relative humidity from mixing ratio."""
340
    p = 1013.25 * units.mbar
341
    temperature = 20. * units.degC
342
    w = 0.012
343
    rh = relative_humidity_from_mixing_ratio(w, temperature, p)
344
    assert_almost_equal(rh, 81.7219 * units.percent, 3)
345
346
347
def test_mixing_ratio_from_specific_humidity():
348
    """Tests mixing ratio from specific humidity."""
349
    q = 0.012
350
    w = mixing_ratio_from_specific_humidity(q)
351
    assert_almost_equal(w, 0.01215, 3)
352
353
354
def test_rh_specific_humidity():
355
    """Tests relative humidity from specific humidity."""
356
    p = 1013.25 * units.mbar
357
    temperature = 20. * units.degC
358
    q = 0.012
359
    rh = relative_humidity_from_specific_humidity(q, temperature, p)
360
    assert_almost_equal(rh, 82.7145 * units.percent, 3)
361
362
363 View Code Duplication
def test_most_unstable_parcel():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
364
    """Tests calculating the most unstable parcel."""
365
    levels = np.array([1000., 959., 867.9]) * units.mbar
366
    temperatures = np.array([18.2, 22.2, 17.4]) * units.celsius
367
    dewpoints = np.array([19., 19., 14.3]) * units.celsius
368
    ret = most_unstable_parcel(levels, temperatures, dewpoints, depth=100 * units.hPa)
369
    assert_almost_equal(ret[0], 959.0 * units.hPa, 6)
370
    assert_almost_equal(ret[1], 22.2 * units.degC, 6)
371
    assert_almost_equal(ret[2], 19.0 * units.degC, 6)
372