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

Fix 410 - Add water cycle intensity indicator #1947

Merged
merged 8 commits into from
Oct 9, 2024
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
5 changes: 3 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^^^^^^^^^
Expand All @@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
13 changes: 13 additions & 0 deletions docs/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -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},
}
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down
8 changes: 8 additions & 0 deletions tests/test_atmos.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
9 changes: 9 additions & 0 deletions tests/test_indices.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
6 changes: 6 additions & 0 deletions xclim/data/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -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."
}
}
6 changes: 6 additions & 0 deletions xclim/data/variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
15 changes: 14 additions & 1 deletion xclim/indicators/atmos/_precip.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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,
)
34 changes: 34 additions & 0 deletions xclim/indices/_multivariate.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"warm_and_dry_days",
"warm_and_wet_days",
"warm_spell_duration_index",
"water_cycle_intensity",
"winter_rain_ratio",
]

Expand Down Expand Up @@ -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
Loading