diff --git a/docs/_templates/overrides/metpy.calc.rst b/docs/_templates/overrides/metpy.calc.rst index 9ebf730e7d7..abd751ead2e 100644 --- a/docs/_templates/overrides/metpy.calc.rst +++ b/docs/_templates/overrides/metpy.calc.rst @@ -73,6 +73,7 @@ Soundings el lcl lfc + lifted_index mixed_layer mixed_layer_cape_cin mixed_parcel diff --git a/docs/references.rst b/docs/references.rst index c2e72a0a56b..578e473aaa1 100644 --- a/docs/references.rst +++ b/docs/references.rst @@ -48,6 +48,11 @@ References *Mon. Wea. Rev.*, **137**, 3137-3148, doi: `10.1175/2009mwr2774.1 `_. +.. [Doswell-Schultz2006] Doswell, C. A., and Schultz, D. M., 2006: On the Use of Indices and + Parameters in Forecasting Severe Storms. *Electronic Journal of Severe Storms + Meteorology*, + `EJSSM `_. + .. [Esterheld2008] Esterheld, J., and Giuliano, D., 2008: Discriminating between Tornadic and Non-Tornadic Supercells: A New Hodograph Technique. *E-Journal Of Severe Storms Meteorology*, **3(2)**, Retrieved May 10, 2018. @@ -79,6 +84,11 @@ References Services and Supporting Research, 2003. `FCM-R19-2003 <_static/FCM-R19-2003-WindchillReport.pdf>`_, 75 pp. +.. [Galway1956] Galway, J. G., 1956: The Lifted Index as a Predictor of Latent Instability. + *American Meteorology Society*, + doi:`10.1175/1520-0477-37.10.528 + `_. + .. [Garratt1994] Garratt, J.R., 1994: *The Atmospheric Boundary Layer*. Cambridge University Press, 316 pp. diff --git a/src/metpy/calc/thermo.py b/src/metpy/calc/thermo.py index 827ed4e5358..e7804b1b828 100644 --- a/src/metpy/calc/thermo.py +++ b/src/metpy/calc/thermo.py @@ -2574,3 +2574,46 @@ def specific_humidity_from_dewpoint(pressure, dewpoint): """ mixing_ratio = saturation_mixing_ratio(pressure, dewpoint) return specific_humidity_from_mixing_ratio(mixing_ratio) + + +@exporter.export +@preprocess_xarray +@check_units('[pressure]', '[temperature]', '[temperature]') +def lifted_index(pressure, temperature, parcel_profile): + """Calculate Lifted Index from the pressure temperature and parcel profile. + + Lifted index formula derived from [Galway1956]_ and referenced by [Doswell-Schultz2006]_: + LI = T500 - Tp500 + where: + T500 is the measured temperature at 500 hPa. + Tp500 is the temperature of the lifted parcel at 500 hPa. + + Calculation of the lifted index is defined as the temperature difference between the + observed 500 hPa temperature and the temperature of a parcel lifted from the + surface to 500 hPa. + + Parameters + ---------- + pressure : `pint.Quantity` + The atmospheric pressure level(s) of interest, in order from highest to + lowest pressure. + temperature : `pint.Quantity` + The atmospheric temperature corresponding to pressure. + parcel_profile : `pint.Quantity` + The temperature profile of the parcel. + + Returns + ------- + `pint.Quantity` + Lifted Index. + + """ + # find the index for the 500 hPa pressure level. + idx = np.where(pressure == 500 * units.hPa) + # find the measured temperature at 500 hPa. + T500 = temperature[idx] + # find the parcel profile temperature at 500 hPa. + Tp500 = parcel_profile[idx] + # calculate the lifted index. + lifted_index = T500 - Tp500.to(units.degC) + return lifted_index diff --git a/tests/calc/test_thermo.py b/tests/calc/test_thermo.py index 57c1388d609..a6e07d8c9a8 100644 --- a/tests/calc/test_thermo.py +++ b/tests/calc/test_thermo.py @@ -11,8 +11,8 @@ brunt_vaisala_period, cape_cin, density, dewpoint, dewpoint_from_relative_humidity, dewpoint_from_specific_humidity, dry_lapse, dry_static_energy, el, equivalent_potential_temperature, - exner_function, isentropic_interpolation, lcl, lfc, mixed_layer, - mixed_layer_cape_cin, mixed_parcel, mixing_ratio, + exner_function, isentropic_interpolation, lcl, lfc, lifted_index, + mixed_layer, mixed_layer_cape_cin, mixed_parcel, mixing_ratio, mixing_ratio_from_relative_humidity, mixing_ratio_from_specific_humidity, moist_lapse, moist_static_energy, most_unstable_cape_cin, most_unstable_parcel, @@ -1557,3 +1557,28 @@ def test_lcl_grid_surface_LCLs(): temp_truth = np.array([15, 9.10391763, 13]) * units.degC assert_array_almost_equal(lcl_pressure, pres_truth, 4) assert_array_almost_equal(lcl_temperature, temp_truth, 4) + + +def test_lifted_index(): + """Test the Lifted Index calculation.""" + pressure = np.array([1014., 1000., 997., 981.2, 947.4, 925., 914.9, 911., + 902., 883., 850., 822.3, 816., 807., 793.2, 770., + 765.1, 753., 737.5, 737., 713., 700., 688., 685., + 680., 666., 659.8, 653., 643., 634., 615., 611.8, + 566.2, 516., 500., 487., 484.2, 481., 475., 460., + 400.]) * units.hPa + temperature = np.array([24.2, 24.2, 24., 23.1, 21., 19.6, 18.7, 18.4, + 19.2, 19.4, 17.2, 15.3, 14.8, 14.4, 13.4, 11.6, + 11.1, 10., 8.8, 8.8, 8.2, 7., 5.6, 5.6, + 5.6, 4.4, 3.8, 3.2, 3., 3.2, 1.8, 1.5, + -3.4, -9.3, -11.3, -13.1, -13.1, -13.1, -13.7, -15.1, + -23.5]) * units.degC + dewpoint = np.array([23.2, 23.1, 22.8, 22., 20.2, 19., 17.6, 17., + 16.8, 15.5, 14., 11.7, 11.2, 8.4, 7., 4.6, + 5., 6., 4.2, 4.1, -1.8, -2., -1.4, -0.4, + -3.4, -5.6, -4.3, -2.8, -7., -25.8, -31.2, -31.4, + -34.1, -37.3, -32.3, -34.1, -37.3, -41.1, -37.7, -58.1, + -57.5]) * units.degC + parcel_prof = parcel_profile(pressure, temperature[0], dewpoint[0]) + LI = lifted_index(pressure, temperature, parcel_prof) + assert_almost_equal(LI, -7.9176350 * units.delta_degree_Celsius, 2)