Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Virtual Temperature in CAPE/CIN calculations #2437

Merged
merged 31 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8a83ef0
first cut at using virtual temperature in parcel profile
mgrover1 Apr 15, 2022
7ab2e47
fix linting with new parcel path class
mgrover1 Apr 15, 2022
1536c9b
fix bugs in initial implementation
mgrover1 Mar 28, 2023
7b7f23e
fix flake8 in thermo
mgrover1 Mar 28, 2023
036be15
Add suggestions from Dan
mgrover1 Mar 29, 2023
84fccfe
compute virtual temperature at the end
mgrover1 Mar 29, 2023
62d4985
revert to original thermo/tests
mgrover1 Apr 3, 2023
911a941
add reverted thermo module
mgrover1 Apr 3, 2023
742a27a
Merge branch 'main' into use-virtual-temp-parcel
mgrover1 Apr 3, 2023
b6aa39a
add missing sweat index calc
mgrover1 Apr 3, 2023
0d9f1fd
add new virtual temperature from dewpoint function
mgrover1 Apr 3, 2023
d393916
add new function to overrides
mgrover1 Apr 3, 2023
22aeec6
use virtual temperature for CAPE
mgrover1 Apr 3, 2023
1af6af1
fix last few failing tests
mgrover1 Apr 3, 2023
994b00b
fix linting issues
mgrover1 Apr 3, 2023
fb7b8e6
update docstring values
mgrover1 Apr 3, 2023
be33d31
fix units for virtual temperature
mgrover1 Apr 3, 2023
7356935
Fix use of parcel moisture profile
mgrover1 Apr 12, 2023
d8c78ac
Add fixed booleans
mgrover1 Apr 13, 2023
404147f
fix failing tests
mgrover1 Apr 13, 2023
c8d13ab
fix line continuation
mgrover1 Apr 13, 2023
dc8ec57
fix the docstring values
mgrover1 Apr 13, 2023
370e091
update docstrings to include virtual temperature
mgrover1 Apr 13, 2023
9015cb2
Update src/metpy/calc/thermo.py
mgrover1 Apr 18, 2023
1a01193
Remove above LCL
mgrover1 Apr 19, 2023
87f718a
Fix variable names in numpy.where
mgrover1 Apr 19, 2023
39e26f8
fix misspelled pressure
mgrover1 Apr 19, 2023
4086007
fix mlcin
mgrover1 Apr 19, 2023
01d94bd
update sensitive sounding test
mgrover1 Apr 24, 2023
612eeba
add suggestion from ryan
mgrover1 Apr 24, 2023
cf9e387
use dewpoint instead of temperature
mgrover1 Apr 24, 2023
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
23 changes: 20 additions & 3 deletions src/metpy/calc/thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,10 +715,19 @@ def el(pressure, temperature, dewpoint, parcel_temperature_profile=None, which='
units.Quantity(np.nan, temperature.units))


class ParcelPathAssumptions():
"""Holds assumptions made about the parcel path during calculations."""

def __init__(self):
self.use_virtual_temperature = True
self.moist_adiabat = 'pseudoadiabatic'


@exporter.export
@preprocess_and_wrap(wrap_like='pressure')
@check_units('[pressure]', '[temperature]', '[temperature]')
def parcel_profile(pressure, temperature, dewpoint):
def parcel_profile(pressure, temperature, dewpoint,
assumptions=ParcelPathAssumptions()):
r"""Calculate the profile a parcel takes through the atmosphere.

The parcel starts at `temperature`, and `dewpoint`, lifted up
Expand Down Expand Up @@ -760,7 +769,8 @@ def parcel_profile(pressure, temperature, dewpoint):
Renamed ``dewpt`` parameter to ``dewpoint``

"""
_, _, _, t_l, _, t_u = _parcel_profile_helper(pressure, temperature, dewpoint)
_, _, _, t_l, _, t_u = _parcel_profile_helper(pressure, temperature, dewpoint,
assumptions=assumptions)
return concatenate((t_l, t_u))


Expand Down Expand Up @@ -911,7 +921,8 @@ def _check_pressure(pressure):
return np.all(pressure[:-1] >= pressure[1:])


def _parcel_profile_helper(pressure, temperature, dewpoint):
def _parcel_profile_helper(pressure, temperature, dewpoint,
assumptions=ParcelPathAssumptions()):
"""Help calculate parcel profiles.

Returns the temperature and pressure, above, below, and including the LCL. The
Expand All @@ -924,6 +935,11 @@ def _parcel_profile_helper(pressure, temperature, dewpoint):
Pressure increases between at least two points in your sounding.
Using scipy.signal.medfilt may fix this."""
raise InvalidSoundingError(msg)

if assumptions.use_virtual_temperature:
specific_humidity = specific_humidity_from_dewpoint(pressure[0], dewpoint)
mixing_ratio = mixing_ratio_from_specific_humidity(specific_humidity)
temperature = virtual_temperature(temperature, mixing_ratio)

# Find the LCL
press_lcl, temp_lcl = lcl(pressure[0], temperature, dewpoint)
Expand Down Expand Up @@ -955,6 +971,7 @@ def _parcel_profile_helper(pressure, temperature, dewpoint):
temp_upper = moist_lapse(unique[::-1], temp_lower[-1]).to(temp_lower.units)
temp_upper = temp_upper[::-1][indices]


# Return profile pieces
return (press_lower[:-1], press_lcl, press_upper[1:],
temp_lower[:-1], temp_lcl, temp_upper[1:])
Expand Down
16 changes: 8 additions & 8 deletions tests/calc/test_thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1261,8 +1261,8 @@ def test_surface_based_cape_cin(array_class):
temperature = array_class([22.2, 14.6, 12., 9.4, 7., -38.], units.celsius)
dewpoint = array_class([19., -11.2, -10.8, -10.4, -10., -53.2], units.celsius)
cape, cin = surface_based_cape_cin(p, temperature, dewpoint)
assert_almost_equal(cape, 75.0535446 * units('joule / kilogram'), 2)
assert_almost_equal(cin, -136.685967 * units('joule / kilogram'), 2)
assert_almost_equal(cape, 327.1348028 * units('joule / kilogram'), 2)
assert_almost_equal(cin, -40.0654774 * units('joule / kilogram'), 2)


def test_surface_based_cape_cin_with_xarray():
Expand All @@ -1285,8 +1285,8 @@ def test_surface_based_cape_cin_with_xarray():
data['temperature'],
data['dewpoint']
)
assert_almost_equal(cape, 75.0535446 * units('joule / kilogram'), 2)
assert_almost_equal(cin, -136.685967 * units('joule / kilogram'), 2)
assert_almost_equal(cape, 327.1348028 * units('joule / kilogram'), 2)
assert_almost_equal(cin, -40.0654774 * units('joule / kilogram'), 2)


def test_profile_with_nans():
Expand Down Expand Up @@ -1326,8 +1326,8 @@ def test_most_unstable_cape_cin_surface():
temperature = np.array([22.2, 14.6, 12., 9.4, 7., -38.]) * units.celsius
dewpoint = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
mucape, mucin = most_unstable_cape_cin(pressure, temperature, dewpoint)
assert_almost_equal(mucape, 75.0535446 * units('joule / kilogram'), 2)
assert_almost_equal(mucin, -136.685967 * units('joule / kilogram'), 2)
assert_almost_equal(mucape, 327.1348028 * units('joule / kilogram'), 2)
assert_almost_equal(mucin, -40.0654774 * units('joule / kilogram'), 2)


def test_most_unstable_cape_cin():
Expand All @@ -1336,8 +1336,8 @@ def test_most_unstable_cape_cin():
temperature = np.array([18.2, 22.2, 17.4, 10., 0., 15]) * units.celsius
dewpoint = np.array([19., 19., 14.3, 0., -10., 0.]) * units.celsius
mucape, mucin = most_unstable_cape_cin(pressure, temperature, dewpoint)
assert_almost_equal(mucape, 157.11404 * units('joule / kilogram'), 4)
assert_almost_equal(mucin, -31.8406578 * units('joule / kilogram'), 4)
assert_almost_equal(mucape, 174.66467 * units('joule / kilogram'), 4)
assert_almost_equal(mucin, 0 * units('joule / kilogram'), 4)


def test_mixed_parcel():
Expand Down