Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/metpy/calc/thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1748,11 +1748,24 @@ def saturation_mixing_ratio(total_press, temperature):

.. math:: r_s = \epsilon \frac{e_s}{p - e_s}

By definition, this value is only defined for conditions where the saturation vapor
pressure (:math:`e_s`) for the given temperature is less than the given total pressure
(:math:`p`). Otherwise, liquid phase water cannot exist in equilibrium and there is only
water vapor present. For any value pairs that fall under this condition, the function will
warn and return NaN.

.. versionchanged:: 1.0
Renamed ``tot_press`` parameter to ``total_press``

"""
return mixing_ratio._nounit(saturation_vapor_pressure._nounit(temperature), total_press)
e_s = saturation_vapor_pressure._nounit(temperature)
undefined = e_s >= total_press
if np.any(undefined):
_warnings.warn('Saturation mixing ratio is undefined for some requested pressure/'
'temperature combinations. Total pressure must be greater than the '
'water vapor saturation pressure for liquid water to be in '
'equilibrium.')
return np.where(undefined, np.nan, mixing_ratio._nounit(e_s, total_press))


@exporter.export
Expand Down
9 changes: 9 additions & 0 deletions tests/calc/test_thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ def test_moist_lapse_starting_points(start, direction):
@pytest.mark.filterwarnings('ignore:overflow encountered in exp:RuntimeWarning')
@pytest.mark.filterwarnings(r'ignore:invalid value encountered in \w*divide:RuntimeWarning')
@pytest.mark.filterwarnings(r'ignore:.*Excess accuracy requested.*:UserWarning')
@pytest.mark.filterwarnings(r'ignore:Saturation mixing ratio is undefined.*:UserWarning')
def test_moist_lapse_failure():
"""Test moist_lapse under conditions that cause the ODE solver to fail."""
p = np.logspace(3, -1, 10) * units.hPa
Expand Down Expand Up @@ -829,6 +830,14 @@ def test_saturation_mixing_ratio_with_xarray():
xr.testing.assert_identical(result['x'], temperature['x'])


def test_saturation_mixing_ratio_bad_value_handling():
"""Test that saturation mixing ratio issues a warning and returns nan with bad values."""
with pytest.warns(UserWarning, match='undefined'):
e_s = saturation_mixing_ratio(10 * units.hPa, 295 * units.kelvin)

assert np.isnan(e_s)


def test_equivalent_potential_temperature():
"""Test equivalent potential temperature calculation."""
p = 1000 * units.mbar
Expand Down
Loading