Completed
Pull Request — master (#454)
by
unknown
01:37
created

test_isentropic_pressure_p_increase()   A

Complexity

Conditions 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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