Completed
Push — master ( 62ca8d...3839f8 )
by Ryan
01:47
created

psychrometric_vapor_pressure_wet()   A

Complexity

Conditions 1

Size

Total Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
c 2
b 0
f 0
dl 0
loc 52
rs 9.4929

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
"""Contains a collection of thermodynamic calculations."""
5
6
from __future__ import division
7
8
import numpy as np
9
import scipy.integrate as si
10
11
from .tools import find_intersections
12
from ..constants import Cp_d, epsilon, kappa, Lv, P0, Rd
13
from ..package_tools import Exporter
14
from ..units import atleast_1d, concatenate, units
15
16
exporter = Exporter(globals())
17
18
sat_pressure_0c = 6.112 * units.millibar
19
20
21
@exporter.export
22
def potential_temperature(pressure, temperature):
23
    r"""Calculate the potential temperature.
24
25
    Uses the Poisson equation to calculation the potential temperature
26
    given `pressure` and `temperature`.
27
28
    Parameters
29
    ----------
30
    pressure : `pint.Quantity`
31
        The total atmospheric pressure
32
    temperature : `pint.Quantity`
33
        The temperature
34
35
    Returns
36
    -------
37
    `pint.Quantity`
38
        The potential temperature corresponding to the the temperature and
39
        pressure.
40
41
    See Also
42
    --------
43
    dry_lapse
44
45
    Notes
46
    -----
47
    Formula:
48
49
    .. math:: \Theta = T (P_0 / P)^\kappa
50
51
    Examples
52
    --------
53
    >>> from metpy.units import units
54
    >>> metpy.calc.potential_temperature(800. * units.mbar, 273. * units.kelvin)
55
    290.9814150577374
56
    """
57
    return temperature * (P0 / pressure).to('dimensionless')**kappa
58
59
60
@exporter.export
61
def dry_lapse(pressure, temperature):
62
    r"""Calculate the temperature at a level assuming only dry processes.
63
64
    This function lifts a parcel starting at `temperature`, conserving
65
    potential temperature. The starting pressure should be the first item in
66
    the `pressure` array.
67
68
    Parameters
69
    ----------
70
    pressure : `pint.Quantity`
71
        The atmospheric pressure level(s) of interest
72
    temperature : `pint.Quantity`
73
        The starting temperature
74
75
    Returns
76
    -------
77
    `pint.Quantity`
78
       The resulting parcel temperature at levels given by `pressure`
79
80
    See Also
81
    --------
82
    moist_lapse : Calculate parcel temperature assuming liquid saturation
83
                  processes
84
    parcel_profile : Calculate complete parcel profile
85
    potential_temperature
86
    """
87
    return temperature * (pressure / pressure[0])**kappa
88
89
90
@exporter.export
91
def moist_lapse(pressure, temperature):
92
    r"""Calculate the temperature at a level assuming liquid saturation processes.
93
94
    This function lifts a parcel starting at `temperature`. The starting
95
    pressure should be the first item in the `pressure` array. Essentially,
96
    this function is calculating moist pseudo-adiabats.
97
98
    Parameters
99
    ----------
100
    pressure : `pint.Quantity`
101
        The atmospheric pressure level(s) of interest
102
    temperature : `pint.Quantity`
103
        The starting temperature
104
105
    Returns
106
    -------
107
    `pint.Quantity`
108
       The temperature corresponding to the the starting temperature and
109
       pressure levels.
110
111
    See Also
112
    --------
113
    dry_lapse : Calculate parcel temperature assuming dry adiabatic processes
114
    parcel_profile : Calculate complete parcel profile
115
116
    Notes
117
    -----
118
    This function is implemented by integrating the following differential
119
    equation:
120
121
    .. math:: \frac{dT}{dP} = \frac{1}{P} \frac{R_d T + L_v r_s}
122
                                {C_{pd} + \frac{L_v^2 r_s \epsilon}{R_d T^2}}
123
124
    This equation comes from [1]_.
125
126
    References
127
    ----------
128
    .. [1] Bakhshaii, A. and R. Stull, 2013: Saturated Pseudoadiabats--A
129
           Noniterative Approximation. J. Appl. Meteor. Clim., 52, 5-15.
130
    """
131
    def dt(t, p):
132
        t = units.Quantity(t, temperature.units)
133
        p = units.Quantity(p, pressure.units)
134
        rs = saturation_mixing_ratio(p, t)
135
        frac = ((Rd * t + Lv * rs) /
136
                (Cp_d + (Lv * Lv * rs * epsilon / (Rd * t * t)))).to('kelvin')
137
        return frac / p
138
    return units.Quantity(si.odeint(dt, atleast_1d(temperature).squeeze(),
139
                                    pressure.squeeze()).T.squeeze(), temperature.units)
140
141
142
@exporter.export
143
def lcl(pressure, temperature, dewpt, max_iters=50, eps=1e-2):
144
    r"""Calculate the lifted condensation level (LCL) using from the starting point.
145
146
    The starting state for the parcel is defined by `temperature`, `dewpt`,
147
    and `pressure`.
148
149
    Parameters
150
    ----------
151
    pressure : `pint.Quantity`
152
        The starting atmospheric pressure
153
    temperature : `pint.Quantity`
154
        The starting temperature
155
    dewpt : `pint.Quantity`
156
        The starting dew point
157
158
    Returns
159
    -------
160
    `(pint.Quantity, pint.Quantity)`
161
        The LCL pressure and temperature
162
163
    Other Parameters
164
    ----------------
165
    max_iters : int, optional
166
        The maximum number of iterations to use in calculation, defaults to 50.
167
    eps : float, optional
168
        The desired absolute error in the calculated value, defaults to 1e-2.
169
170
    See Also
171
    --------
172
    parcel_profile
173
174
    Notes
175
    -----
176
    This function is implemented using an iterative approach to solve for the
177
    LCL. The basic algorithm is:
178
179
    1. Find the dew point from the LCL pressure and starting mixing ratio
180
    2. Find the LCL pressure from the starting temperature and dewpoint
181
    3. Iterate until convergence
182
183
    The function is guaranteed to finish by virtue of the `max_iters` counter.
184
    """
185
    w = mixing_ratio(saturation_vapor_pressure(dewpt), pressure)
186
    new_p = p = pressure
187
    eps = units.Quantity(eps, p.units)
188
    while max_iters:
189
        td = dewpoint(vapor_pressure(p, w))
190
        new_p = pressure * (td / temperature) ** (1. / kappa)
191
        if np.abs(new_p - p).max() < eps:
192
            break
193
        p = new_p
194
        max_iters -= 1
195
196
    else:
197
        # We have not converged
198
        raise RuntimeError('LCL calculation has not converged.')
199
200
    return new_p, td
201
202
203
@exporter.export
204
def lfc(pressure, temperature, dewpt):
205
    r"""Calculate the level of free convection (LFC).
206
207
    This works by finding the first intersection of the ideal parcel path and
208
    the measured parcel temperature.
209
210
    Parameters
211
    ----------
212
    pressure : `pint.Quantity`
213
        The atmospheric pressure
214
    temperature : `pint.Quantity`
215
        The temperature at the levels given by `pressure`
216
    dewpt : `pint.Quantity`
217
        The dew point at the levels given by `pressure`
218
219
    Returns
220
    -------
221
    `pint.Quantity`
222
        The LFC
223
224
    See Also
225
    --------
226
    parcel_profile
227
    """
228
    ideal_profile = parcel_profile(pressure, temperature[0], dewpt[0]).to('degC')
229
230
    # The parcel profile and data have the same first data point, so we ignore
231
    # that point to get the real first intersection for the LFC calculation.
232
    x, y = find_intersections(pressure[1:], ideal_profile[1:], temperature[1:])
233
    if len(x) == 0:
234
        return None, None
235
    else:
236
        return x[0], y[0]
237
238
239
@exporter.export
240
def el(pressure, temperature, dewpt):
241
    r"""Calculate the equilibrium level.
242
243
    This works by finding the last intersection of the ideal parcel path and
244
    the measured environmental temperature. If there is one or fewer intersections, there is
245
    no equilibrium level.
246
247
    Parameters
248
    ----------
249
    pressure : `pint.Quantity`
250
        The atmospheric pressure
251
    temperature : `pint.Quantity`
252
        The temperature at the levels given by `pressure`
253
    dewpt : `pint.Quantity`
254
        The dew point at the levels given by `pressure`
255
256
    Returns
257
    -------
258
    `pint.Quantity, pint.Quantity`
259
        The EL pressure and temperature
260
261
    See Also
262
    --------
263
    parcel_profile
264
    """
265
    ideal_profile = parcel_profile(pressure, temperature[0], dewpt[0]).to('degC')
266
    x, y = find_intersections(pressure[1:], ideal_profile[1:], temperature[1:])
267
268
    # If there is only one intersection, it's the LFC and we return None.
269
    if len(x) <= 1:
270
        return None, None
271
    else:
272
        return x[-1], y[-1]
273
274
275
@exporter.export
276
def parcel_profile(pressure, temperature, dewpt):
277
    r"""Calculate the profile a parcel takes through the atmosphere.
278
279
    The parcel starts at `temperature`, and `dewpt`, lifted up
280
    dry adiabatically to the LCL, and then moist adiabatically from there.
281
    `pressure` specifies the pressure levels for the profile.
282
283
    Parameters
284
    ----------
285
    pressure : `pint.Quantity`
286
        The atmospheric pressure level(s) of interest. The first entry should be the starting
287
        point pressure.
288
    temperature : `pint.Quantity`
289
        The starting temperature
290
    dewpt : `pint.Quantity`
291
        The starting dew point
292
293
    Returns
294
    -------
295
    `pint.Quantity`
296
        The parcel temperatures at the specified pressure levels.
297
298
    See Also
299
    --------
300
    lcl, moist_lapse, dry_lapse
301
    """
302
    # Find the LCL
303
    l = lcl(pressure[0], temperature, dewpt)[0].to(pressure.units)
304
305
    # Find the dry adiabatic profile, *including* the LCL. We need >= the LCL in case the
306
    # LCL is included in the levels. It's slightly redundant in that case, but simplifies
307
    # the logic for removing it later.
308
    press_lower = concatenate((pressure[pressure >= l], l))
309
    t1 = dry_lapse(press_lower, temperature)
310
311
    # Find moist pseudo-adiabatic profile starting at the LCL
312
    press_upper = concatenate((l, pressure[pressure < l]))
313
    t2 = moist_lapse(press_upper, t1[-1]).to(t1.units)
314
315
    # Return LCL *without* the LCL point
316
    return concatenate((t1[:-1], t2[1:]))
317
318
319
@exporter.export
320
def vapor_pressure(pressure, mixing):
321
    r"""Calculate water vapor (partial) pressure.
322
323
    Given total `pressure` and water vapor `mixing` ratio, calculates the
324
    partial pressure of water vapor.
325
326
    Parameters
327
    ----------
328
    pressure : `pint.Quantity`
329
        total atmospheric pressure
330
    mixing : `pint.Quantity`
331
        dimensionless mass mixing ratio
332
333
    Returns
334
    -------
335
    `pint.Quantity`
336
        The ambient water vapor (partial) pressure in the same units as
337
        `pressure`.
338
339
    Notes
340
    -----
341
    This function is a straightforward implementation of the equation given in many places,
342
    such as [2]_:
343
344
    .. math:: e = p \frac{r}{r + \epsilon}
345
346
    References
347
    ----------
348
    .. [2] Hobbs, Peter V. and Wallace, John M., 1977: Atmospheric Science, an Introductory
349
           Survey. 71.
350
351
    See Also
352
    --------
353
    saturation_vapor_pressure, dewpoint
354
    """
355
    return pressure * mixing / (epsilon + mixing)
356
357
358
@exporter.export
359
def saturation_vapor_pressure(temperature):
360
    r"""Calculate the saturation water vapor (partial) pressure.
361
362
    Parameters
363
    ----------
364
    temperature : `pint.Quantity`
365
        The temperature
366
367
    Returns
368
    -------
369
    `pint.Quantity`
370
        The saturation water vapor (partial) pressure
371
372
    See Also
373
    --------
374
    vapor_pressure, dewpoint
375
376
    Notes
377
    -----
378
    Instead of temperature, dewpoint may be used in order to calculate
379
    the actual (ambient) water vapor (partial) pressure.
380
381
    The formula used is that from Bolton 1980 [3]_ for T in degrees Celsius:
382
383
    .. math:: 6.112 e^\frac{17.67T}{T + 243.5}
384
385
    References
386
    ----------
387
    .. [3] Bolton, D., 1980: The Computation of Equivalent Potential
388
           Temperature. Mon. Wea. Rev., 108, 1046-1053.
389
    """
390
    # Converted from original in terms of C to use kelvin. Using raw absolute values of C in
391
    # a formula plays havoc with units support.
392
    return sat_pressure_0c * np.exp(17.67 * (temperature - 273.15 * units.kelvin) /
393
                                    (temperature - 29.65 * units.kelvin))
394
395
396
@exporter.export
397
def dewpoint_rh(temperature, rh):
398
    r"""Calculate the ambient dewpoint given air temperature and relative humidity.
399
400
    Parameters
401
    ----------
402
    temperature : `pint.Quantity`
403
        Air temperature
404
    rh : `pint.Quantity`
405
        Relative humidity expressed as a ratio in the range [0, 1]
406
407
    Returns
408
    -------
409
    `pint.Quantity`
410
        The dew point temperature
411
412
    See Also
413
    --------
414
    dewpoint, saturation_vapor_pressure
415
    """
416
    return dewpoint(rh * saturation_vapor_pressure(temperature))
417
418
419
@exporter.export
420
def dewpoint(e):
421
    r"""Calculate the ambient dewpoint given the vapor pressure.
422
423
    Parameters
424
    ----------
425
    e : `pint.Quantity`
426
        Water vapor partial pressure
427
428
    Returns
429
    -------
430
    `pint.Quantity`
431
        Dew point temperature
432
433
    See Also
434
    --------
435
    dewpoint_rh, saturation_vapor_pressure, vapor_pressure
436
437
    Notes
438
    -----
439
    This function inverts the Bolton 1980 [4]_ formula for saturation vapor
440
    pressure to instead calculate the temperature. This yield the following
441
    formula for dewpoint in degrees Celsius:
442
443
    .. math:: T = \frac{243.5 log(e / 6.112)}{17.67 - log(e / 6.112)}
444
445
    References
446
    ----------
447
    .. [4] Bolton, D., 1980: The Computation of Equivalent Potential
448
           Temperature. Mon. Wea. Rev., 108, 1046-1053.
449
    """
450
    val = np.log(e / sat_pressure_0c)
451
    return 0. * units.degC + 243.5 * units.delta_degC * val / (17.67 - val)
452
453
454
@exporter.export
455
def mixing_ratio(part_press, tot_press, molecular_weight_ratio=epsilon):
456
    r"""Calculate the mixing ratio of a gas.
457
458
    This calculates mixing ratio given its partial pressure and the total pressure of
459
    the air. There are no required units for the input arrays, other than that
460
    they have the same units.
461
462
    Parameters
463
    ----------
464
    part_press : `pint.Quantity`
465
        Partial pressure of the constituent gas
466
    tot_press : `pint.Quantity`
467
        Total air pressure
468
    molecular_weight_ratio : `pint.Quantity` or float, optional
469
        The ratio of the molecular weight of the constituent gas to that assumed
470
        for air. Defaults to the ratio for water vapor to dry air
471
        (:math:`\epsilon\approx0.622`).
472
473
    Returns
474
    -------
475
    `pint.Quantity`
476
        The (mass) mixing ratio, dimensionless (e.g. Kg/Kg or g/g)
477
478
    Notes
479
    -----
480
    This function is a straightforward implementation of the equation given in many places,
481
    such as [5]_:
482
483
    .. math:: r = \epsilon \frac{e}{p - e}
484
485
    References
486
    ----------
487
    .. [5] Hobbs, Peter V. and Wallace, John M., 1977: Atmospheric Science, an Introductory
488
           Survey. 73.
489
490
    See Also
491
    --------
492
    saturation_mixing_ratio, vapor_pressure
493
    """
494
    return molecular_weight_ratio * part_press / (tot_press - part_press)
495
496
497
@exporter.export
498
def saturation_mixing_ratio(tot_press, temperature):
499
    r"""Calculate the saturation mixing ratio of water vapor.
500
501
    This calculation is given total pressure and the temperature. The implementation
502
    uses the formula outlined in [6]_.
503
504
    Parameters
505
    ----------
506
    tot_press: `pint.Quantity`
507
        Total atmospheric pressure
508
    temperature: `pint.Quantity`
509
        The temperature
510
511
    Returns
512
    -------
513
    `pint.Quantity`
514
        The saturation mixing ratio, dimensionless
515
516
    References
517
    ----------
518
    .. [6] Hobbs, Peter V. and Wallace, John M., 1977: Atmospheric Science, an Introductory
519
           Survey. 73.
520
    """
521
    return mixing_ratio(saturation_vapor_pressure(temperature), tot_press)
522
523
524
@exporter.export
525
def equivalent_potential_temperature(pressure, temperature):
526
    r"""Calculate equivalent potential temperature.
527
528
    This calculation must be given an air parcel's pressure and temperature.
529
    The implementation uses the formula outlined in [7]_.
530
531
    Parameters
532
    ----------
533
    pressure: `pint.Quantity`
534
        Total atmospheric pressure
535
    temperature: `pint.Quantity`
536
        The temperature
537
538
    Returns
539
    -------
540
    `pint.Quantity`
541
        The corresponding equivalent potential temperature of the parcel
542
543
    Notes
544
    -----
545
    .. math:: \Theta_e = \Theta e^\frac{L_v r_s}{C_{pd} T}
546
547
    References
548
    ----------
549
    .. [7] Hobbs, Peter V. and Wallace, John M., 1977: Atmospheric Science, an Introductory
550
           Survey. 78-79.
551
    """
552
    pottemp = potential_temperature(pressure, temperature)
553
    smixr = saturation_mixing_ratio(pressure, temperature)
554
    return pottemp * np.exp(Lv * smixr / (Cp_d * temperature))
555
556
557
@exporter.export
558
def virtual_temperature(temperature, mixing, molecular_weight_ratio=epsilon):
559
    r"""Calculate virtual temperature.
560
561
    This calculation must be given an air parcel's temperature and mixing ratio.
562
    The implementation uses the formula outlined in [8]_.
563
564
    Parameters
565
    ----------
566
    temperature: `pint.Quantity`
567
        The temperature
568
    mixing : `pint.Quantity`
569
        dimensionless mass mixing ratio
570
    molecular_weight_ratio : `pint.Quantity` or float, optional
571
        The ratio of the molecular weight of the constituent gas to that assumed
572
        for air. Defaults to the ratio for water vapor to dry air
573
        (:math:`\epsilon\approx0.622`).
574
575
    Returns
576
    -------
577
    `pint.Quantity`
578
        The corresponding virtual temperature of the parcel
579
580
    Notes
581
    -----
582
    .. math:: T_v = T \frac{\text{w} + \epsilon}{\epsilon\,(1 + \text{w})}
583
584
    References
585
    ----------
586
    .. [8] Hobbs, Peter V. and Wallace, John M., 2006: Atmospheric Science, an Introductory
587
           Survey. 2nd ed. 80.
588
    """
589
    return temperature * ((mixing + molecular_weight_ratio) /
590
                          (molecular_weight_ratio * (1 + mixing)))
591
592
593
@exporter.export
594
def virtual_potential_temperature(pressure, temperature, mixing,
595
                                  molecular_weight_ratio=epsilon):
596
    r"""Calculate virtual potential temperature.
597
598
    This calculation must be given an air parcel's pressure, temperature, and mixing ratio.
599
    The implementation uses the formula outlined in [9]_.
600
601
    Parameters
602
    ----------
603
    pressure: `pint.Quantity`
604
        Total atmospheric pressure
605
    temperature: `pint.Quantity`
606
        The temperature
607
    mixing : `pint.Quantity`
608
        dimensionless mass mixing ratio
609
    molecular_weight_ratio : `pint.Quantity` or float, optional
610
        The ratio of the molecular weight of the constituent gas to that assumed
611
        for air. Defaults to the ratio for water vapor to dry air
612
        (:math:`\epsilon\approx0.622`).
613
614
    Returns
615
    -------
616
    `pint.Quantity`
617
        The corresponding virtual potential temperature of the parcel
618
619
    Notes
620
    -----
621
    .. math:: \Theta_v = \Theta \frac{\text{w} + \epsilon}{\epsilon\,(1 + \text{w})}
622
623
    References
624
    ----------
625
    .. [9] Markowski, Paul and Richardson, Yvette, 2010: Mesoscale Meteorology in the
626
           Midlatitudes. 13.
627
    """
628
    pottemp = potential_temperature(pressure, temperature)
629
    return virtual_temperature(pottemp, mixing, molecular_weight_ratio)
630
631
632
@exporter.export
633
def density(pressure, temperature, mixing, molecular_weight_ratio=epsilon):
634
    r"""Calculate density.
635
636
    This calculation must be given an air parcel's pressure, temperature, and mixing ratio.
637
    The implementation uses the formula outlined in [10]_.
638
639
    Parameters
640
    ----------
641
    temperature: `pint.Quantity`
642
        The temperature
643
    pressure: `pint.Quantity`
644
        Total atmospheric pressure
645
    mixing : `pint.Quantity`
646
        dimensionless mass mixing ratio
647
    molecular_weight_ratio : `pint.Quantity` or float, optional
648
        The ratio of the molecular weight of the constituent gas to that assumed
649
        for air. Defaults to the ratio for water vapor to dry air
650
        (:math:`\epsilon\approx0.622`).
651
652
    Returns
653
    -------
654
    `pint.Quantity`
655
        The corresponding density of the parcel
656
657
    Notes
658
    -----
659
    .. math:: \rho = \frac{p}{R_dT_v}
660
661
    References
662
    ----------
663
    .. [10] Hobbs, Peter V. and Wallace, John M., 2006: Atmospheric Science, an Introductory
664
           Survey. 2nd ed. 67.
665
    """
666
    virttemp = virtual_temperature(temperature, mixing, molecular_weight_ratio)
667
    return (pressure / (Rd * virttemp)).to(units.kilogram / units.meter ** 3)
668
669
670
@exporter.export
671
def relative_humidity_wet_psychrometric(dry_bulb_temperature, web_bulb_temperature,
672
                                        pressure, **kwargs):
673
    r"""Calculate the relative humidity with wet bulb and dry bulb temperatures.
674
675
    Parameters
676
    ----------
677
    dry_bulb_temperature: `pint.Quantity`
678
        Dry bulb temperature
679
    web_bulb_temperature: `pint.Quantity`
680
        Wet bulb temperature
681
    pressure: `pint.Quantity`
682
        Total atmospheric pressure
683
684
    Returns
685
    -------
686
    `pint.Quantity`
687
        Relative humidity
688
689
    Notes
690
    -----
691
    .. math:: RH = 100 \frac{e}{e_s}
692
693
    * :math:`RH` is relative humidity
694
    * :math:`e` is vapor pressure from the wet psychrometric calculation
695
    * :math:`e_s` is the saturation vapor pressure
696
697
    References
698
    ----------
699
    .. [10] WMO GUIDE TO METEOROLOGICAL INSTRUMENTS AND METHODS OF OBSERVATION WMO-No.8
700
       (2008 edition, Updated in 2010) : PART 4
701
       https://www.wmo.int/pages/prog/www/IMOP/CIMO-Guide.html
702
703
    .. [11] Fan, Jinpeng. "Determination of the psychrometer coefficient A of the WMO
704
       reference psychrometer by comparison with a standard gravimetric hygrometer."
705
       Journal of Atmospheric and Oceanic Technology 4.1 (1987): 239-244.
706
707
    See Also
708
    --------
709
    psychrometric_vapor_pressure_wet, saturation_vapor_pressure
710
    """
711
    return (100 * units.percent * psychrometric_vapor_pressure_wet(dry_bulb_temperature,
712
            web_bulb_temperature, pressure, **kwargs) /
713
            saturation_vapor_pressure(dry_bulb_temperature))
714
715
716
@exporter.export
717
def psychrometric_vapor_pressure_wet(dry_bulb_temperature, wet_bulb_temperature, pressure,
718
                                     psychrometer_coefficient=6.21e-4 / units.kelvin):
719
    r"""Calculate the vapor pressure with wet bulb and dry bulb temperatures.
720
721
    Parameters
722
    ----------
723
    dry_bulb_temperature: `pint.Quantity`
724
        Dry bulb temperature
725
    web_bulb_temperature: `pint.Quantity`
726
        Wet bulb temperature
727
    pressure: `pint.Quantity`
728
        Total atmospheric pressure
729
    psychrometer coefficient: `pint.Quantity`
730
        Psychrometer coefficient
731
732
    Returns
733
    -------
734
    `pint.Quantity`
735
        Vapor pressure
736
737
    Notes
738
    -----
739
    .. math:: e' = e'_w(T_w) - A p (T - T_w)
740
741
    * :math:`e'` is vapor pressure
742
    * :math:`e'_w(T_w)` is the saturation vapor pressure with respect to water at temperature
743
      :math:`T_w`
744
    * :math:`p` is the pressure of the wet bulb
745
    * :math:`T` is the temperature of the dry bulb
746
    * :math:`T_w` is the temperature of the wet bulb
747
    * :math:`A` is the psychrometer coefficient
748
749
    Psychrometer coefficient depends on the specific instrument being used and the ventilation
750
    of the instrument.
751
752
    References
753
    ----------
754
    .. [12] WMO GUIDE TO METEOROLOGICAL INSTRUMENTS AND METHODS OF OBSERVATION WMO-No.8
755
       (2008 edition, Updated in 2010) : PART 4
756
       https://www.wmo.int/pages/prog/www/IMOP/CIMO-Guide.html
757
758
    .. [13] Fan, Jinpeng. "Determination of the psychrometer coefficient A of the WMO reference
759
       psychrometer by comparison with a standard gravimetric hygrometer."
760
       Journal of Atmospheric and Oceanic Technology 4.1 (1987): 239-244.
761
762
    See Also
763
    --------
764
    saturation_vapor_pressure
765
    """
766
    return (saturation_vapor_pressure(wet_bulb_temperature) - psychrometer_coefficient *
767
            pressure * (dry_bulb_temperature - wet_bulb_temperature).to('kelvin'))
768