Completed
Pull Request — master (#454)
by
unknown
01:33
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
def test_lfc_basic():
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
def test_lfc_inversion():
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 = [100000., 95000., 90000., 85000.] * units.Pa
304
    tmp = np.ones((4, 5, 5))
305
    tmp[0, :] = 296.
306
    tmp[1, :] = 292.
307
    tmp[2, :] = 290
308
    tmp[3, :] = 288.
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 View Code Duplication
def test_isentropic_pressure_adition_args():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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 View Code Duplication
def test_isentropic_pressure_p_increase_rh_out():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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