diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4368d61a5..59eebe81a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,7 +4,7 @@ Changelog v0.53.0 (unreleased) -------------------- -Contributors to this version: Adrien Lamarche (:user:`LamAdr`), Trevor James Smith (:user:`Zeitsperre`), Éric Dupuis (:user:`coxipi`), Pascal Bourgault (:user:`aulemahal`), Sascha Hofmann (:user:`saschahofmann`). +Contributors to this version: Adrien Lamarche (:user:`LamAdr`), Trevor James Smith (:user:`Zeitsperre`), Éric Dupuis (:user:`coxipi`), Pascal Bourgault (:user:`aulemahal`), Sascha Hofmann (:user:`saschahofmann`), David Huard (:user:`huard`). Announcements ^^^^^^^^^^^^^ @@ -14,8 +14,9 @@ Announcements New indicators ^^^^^^^^^^^^^^ * New ``heat_spell_frequency``, ``heat_spell_max_length`` and ``heat_spell_total_length`` : spell length statistics on a bivariate condition that uses the average over a window by default. (:pull:`1885`). -* New ``hot_spell_max_magnitude`` : yields the magnitude of the most intensive heat wave. (:pull:`1926`). +* New ``hot_spell_max_magnitude``: yields the magnitude of the most intensive heat wave. (:pull:`1926`). * New ``chill_portion`` and ``chill_unit``: chill portion based on the Dynamic Model and chill unit based on the Utah model indicators. (:issue:`1753`, :pull:`1909`). +* New ``water_cycle_intensity``: yields the sum of precipitation and actual evapotranspiration. (:issue:`410`, :pull:`1947`). New features and enhancements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/references.bib b/docs/references.bib index bc4ed54fb..6947caccd 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -2307,3 +2307,16 @@ @article{zhang_high_2022 urldate = {2024-10-03}, langid = {english} } + +@article{huntington_2018, + title = {A new indicator framework for quantifying the intensity of the terrestrial water cycle}, + journal = {Journal of Hydrology}, + volume = {559}, + pages = {361-372}, + year = {2018}, + issn = {0022-1694}, + doi = {https://doi.org/10.1016/j.jhydrol.2018.02.048}, + url = {https://www.sciencedirect.com/science/article/pii/S0022169418301276}, + author = {Thomas G. Huntington and Peter K. Weiskel and David M. Wolock and Gregory J. McCabe}, + keywords = {Intensification of the water cycle, Water cycle intensity, Water-balance model, Evapotranspiration, Aridification}, +} diff --git a/tests/conftest.py b/tests/conftest.py index 08858a306..ba3597b17 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -81,6 +81,12 @@ def pr_series(): return _pr_series +@pytest.fixture +def evspsbl_series(): + """Return precipitation time series.""" + return partial(test_timeseries, variable="evspsbl") + + @pytest.fixture def prc_series(): """Return convective precipitation time series.""" diff --git a/tests/test_atmos.py b/tests/test_atmos.py index 80757e5f7..862fa4922 100644 --- a/tests/test_atmos.py +++ b/tests/test_atmos.py @@ -656,3 +656,11 @@ def test_chill_portions(atmosds): # due to implementation details exp = [np.nan, 99.91534493, 92.5473925, 99.03177047, np.nan] np.testing.assert_allclose(cp.isel(location=0), exp, rtol=1e-03) + + +def test_water_cycle_intensity(pr_series, evspsbl_series): + pr = pr_series(np.ones(31)) + evspsbl = evspsbl_series(np.ones(31)) + + wci = atmos.water_cycle_intensity(pr=pr, evspsbl=evspsbl, freq="MS") + np.testing.assert_allclose(wci, 2 * 60 * 60 * 24 * 31) diff --git a/tests/test_indices.py b/tests/test_indices.py index f32279b8d..2dd2ea261 100644 --- a/tests/test_indices.py +++ b/tests/test_indices.py @@ -3983,3 +3983,12 @@ def test_simple(self, sfcWind_series): pb = xci.wind_power_potential(b) np.testing.assert_array_almost_equal(pa, pb, decimal=6) + + +class TestWaterCycleIntensity: + def test_simple(self, pr_series, evspsbl_series): + pr = pr_series(np.ones(31)) + evspsbl = evspsbl_series(np.ones(31)) + + wci = xci.water_cycle_intensity(pr=pr, evspsbl=evspsbl, freq="MS") + np.testing.assert_allclose(wci, 2 * 60 * 60 * 24 * 31) diff --git a/xclim/data/fr.json b/xclim/data/fr.json index 64bae13e1..94822e704 100644 --- a/xclim/data/fr.json +++ b/xclim/data/fr.json @@ -1421,5 +1421,11 @@ "abstract": "Les unités de froid (chill units) sont une mesure du potentiel de débourrement de différentes récoltes basée sur le modèle Utah.", "long_name": "Unités de froid selon le modèle Utah", "description": "Les unités de froid (chill units) sont une mesure du potentiel de débourrement de différentes récoltes basée sur le modèle Utah." + }, + "WATER_CYCLE_INTENSITY": { + "title": "Intensité du cycle de l'eau", + "long_name": "Intensité du cycle de l'eau", + "description": "Indice {freq} de l'intensité du cycle de l'eau, défini comme la somme de la précipitation et de l'évapotranspiration.", + "abstract": "la somme de la précipitation et de l'évapotranspiration." } } diff --git a/xclim/data/variables.yml b/xclim/data/variables.yml index 0a7553b0c..a02194514 100644 --- a/xclim/data/variables.yml +++ b/xclim/data/variables.yml @@ -16,6 +16,12 @@ variables: cell_methods: "time: mean" description: The amount of water, in all phases, flowing in the river channel and flood plain. standard_name: water_volume_transport_in_river_channel + evspsbl: + canonical_units: kg m-2 s-1 + cell_methods: "time: mean" + description: Actual evapotranspiration flux. + dimensions: "[discharge]" + standard_name: water_evapotranspiration_flux evspsblpot: canonical_units: kg m-2 s-1 cell_methods: "time: mean" diff --git a/xclim/indicators/atmos/_precip.py b/xclim/indicators/atmos/_precip.py index c0787da6f..79ba58d61 100644 --- a/xclim/indicators/atmos/_precip.py +++ b/xclim/indicators/atmos/_precip.py @@ -57,6 +57,7 @@ "standardized_precipitation_index", "warm_and_dry_days", "warm_and_wet_days", + "water_cycle_intensity", "wet_precip_accumulation", "wet_spell_frequency", "wet_spell_max_length", @@ -790,7 +791,19 @@ class HrPrecip(Hourly): units=["", "", "days"], abstract="Start time, end time and length of the rain season, notably useful for West Africa (sivakumar, 1998). " "The rain season starts with a period of abundant rainfall, followed by a period without prolonged dry sequences, " - "which must happen before a given date. The rain season stops during a dry period happening after a given date", + "which must happen before a given date. The rain season stops during a dry period happening after a given date.", cell_methods="", compute=indices.rain_season, ) + +water_cycle_intensity = PrecipWithIndexing( + title="Water cycle intensity", + identifier="water_cycle_intensity", + realm="atmos", + units="mm", + long_name="Water cycle intensity", + description="The {freq} water cycle intensity, defined as the sum of precipitation and actual evapotranspiration.", + abstract="The sum of precipitation and actual evapotranspiration.", + cell_methods="time: sum over days", + compute=indices.water_cycle_intensity, +) diff --git a/xclim/indices/_multivariate.py b/xclim/indices/_multivariate.py index f10e6fae6..c04c8c58b 100644 --- a/xclim/indices/_multivariate.py +++ b/xclim/indices/_multivariate.py @@ -58,6 +58,7 @@ "warm_and_dry_days", "warm_and_wet_days", "warm_spell_duration_index", + "water_cycle_intensity", "winter_rain_ratio", ] @@ -1865,3 +1866,36 @@ def blowing_snow( out = cond.resample(time=freq).sum(dim="time") out = out.assign_attrs(units=to_agg_units(out, snd, "count")) return out + + +@declare_units(pr="[precipitation]", evspsbl="[precipitation]") +def water_cycle_intensity( + pr: xarray.DataArray, evspsbl: xarray.DataArray, freq="YS" +) -> xarray.DataArray: + """Water cycle intensity. + + The sum of precipitation and actual evapotranspiration. + + Parameters + ---------- + pr : xarray.DataArray + Precipitation flux. + evspsbl : xarray.DataArray + Actual evapotranspiration flux. + + Returns + ------- + xarray.DataArray + The sum of precipitation and actual evapotranspiration for each period. + + References + ---------- + :cite:cts:`huntington_2018` + """ + pr = convert_units_to(pr, evspsbl) + + # Water cycle intensity + wci = (pr + evspsbl).assign_attrs(units=pr.units) + wci = rate2amount(wci) + wci = wci.resample(time=freq).sum(dim="time").assign_attrs(units=wci.units) + return wci