{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Inputs for the Probable Maximum flood (PMF)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Probable Maximum Precipitation (PMP)\n", "\n", "Probable Maximum Precipitation (PMP) is the theoretical maximum amount of precipitation that could occur at a specific location within a given period of time, considering the most extreme meteorological conditions. PMP is a critical parameter in hydrology, especially for the design of infrastructure such as dams, reservoirs, and drainage systems.\n", "\n", "There are several methods for calculating PMP, each varying in complexity and the type of data used. The method currently implemented in `xHydro` is based on the approach outlined by [Clavet-Gaumont et al. (2017)](https://doi.org/10.1016/j.ejrh.2017.07.003). This method involves maximizing the precipitable water over a given location, which refers to the total water vapor in the atmosphere that could potentially be converted into precipitation under ideal conditions. By maximizing this value, the method estimates the maximum precipitation that could theoretically occur at the location.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "import hvplot.xarray\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pooch\n", "import xarray as xr\n", "import xclim\n", "\n", "import xhydro as xh\n", "from xhydro.testing.helpers import deveraux" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Acquiring data\n", "\n", "The acquisition of climatological data is outside the scope of `xHydro`. However, some examples of how to obtain and handle such data are provided in the [GIS operations](../gis.ipynb) and [Use Case Example](../use_case.ipynb) notebooks. For this notebook, we will use a test dataset consisting of 2 years and 3x3 grid cells from CanESM5 climate model data. In a real application, it would be preferable to have as many years of data as possible.\n", "\n", "To perform the analysis, certain climatological variables are required.\n", "\n", "- **Daily Timestep Variables**:\n", " - `pr` → Precipitation flux\n", " - `snw` → Snow water equivalent\n", " - `hus` → Specific humidity for multiple pressure levels\n", " - `zg` → Geopotential height for multiple pressure levels\n", "\n", "- **Fixed Field Variables**:\n", " - `orog` → Surface altitude\n", "\n", "In cold regions, it may be necessary to split total precipitation into rainfall and snowfall components. Many climate models already provide this data separately. However, if this data is not directly available, libraries such as `xclim` can approximate the split using precipitation and temperature data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "import xhydro as xh\n", "\n", "path_day_zip = deveraux().fetch(\n", " \"pmp/CMIP.CCCma.CanESM5.historical.r1i1p1f1.day.gn.zarr.zip\",\n", " pooch.Unzip(),\n", ")\n", "ds_day = xr.open_zarr(Path(path_day_zip[0]).parents[0])\n", "\n", "path_fx_zip = deveraux().fetch(\n", " \"pmp/CMIP.CCCma.CanESM5.historical.r1i1p1f1.fx.gn.zarr.zip\",\n", " pooch.Unzip(),\n", ")\n", "ds_fx = xr.open_zarr(Path(path_fx_zip[0]).parents[0])\n", "\n", "# There are a few issues with attributes in this dataset that we need to address\n", "ds_day[\"pr\"].attrs = {\"units\": \"mm\", \"long_name\": \"precipitation\"}\n", "ds_day[\"prsn\"].attrs = {\"units\": \"mm\", \"long_name\": \"snowfall\"}\n", "ds_day[\"rf\"].attrs = {\"units\": \"mm\", \"long_name\": \"rainfall\"}\n", "\n", "# Combine both datasets\n", "ds = ds_day.convert_calendar(\"standard\")\n", "ds[\"orog\"] = ds_fx[\"orog\"]\n", "ds" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Computing the PMP\n", "\n", "The method outlined by [Clavet-Gaumont et al. (2017)](https://doi.org/10.1016/j.ejrh.2017.07.003) follows these steps:\n", "\n", "1. **Identification of Major Precipitation Events**: \n", " The first step involves identifying the major precipitation events that will be maximized. This is done by filtering events based on a specified threshold.\n", "\n", "2. **Computation of Monthly 100-Year Precipitable Water**: \n", " The next step involves calculating the 100-year precipitable water on a monthly basis using the Generalized Extreme Value (GEV) distribution, with a maximum cap of 20% greater than the largest observed value.\n", "\n", "3. **Maximization of Precipitation During Events**: \n", " In this step, the precipitation events are maximized based on the ratio between the 100-year monthly precipitable water and the precipitable water during the major precipitation events. In snow-free regions, this is the final result.\n", "\n", "4. **Seasonal Separation in Cold Regions**: \n", " In cold regions, the results are separated into seasons (e.g., spring, summer) to account for snow during the computation of Probable Maximum Floods (PMF).\n", "\n", "This method provides a comprehensive approach for estimating the PMP, taking into account both temperature and precipitation variations across different regions and seasons.\n", "\n", "\n", "### Major precipitation events\n", "\n", "The first step in calculating the Probable Maximum Precipitation (PMP) involves filtering the precipitation data to retain only the events that exceed a certain threshold. These major precipitation events will be maximized in subsequent steps. The function `xh.indicators.pmp.major_precipitation_events` can be used for this purpose. It also provides the option to sum precipitation over a specified number of days, which can help aggregate storm events. For 2D data, such as in this example, each grid point is treated independently.\n", "\n", "In this example, we will filter out the 10% most intense storms to avoid overemphasizing smaller precipitation events during the maximization process. Additionally, we will focus on rainfall (`rf`) rather than total precipitation (`pr`) to exclude snowstorms and ensure that we are only considering liquid precipitation events.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "help(xh.indicators.pmp.major_precipitation_events)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "precipitation_events = xh.indicators.pmp.major_precipitation_events(\n", " ds.rf, windows=[1], quantile=0.9, min_prec=\"0.1 mm\"\n", ")\n", "\n", "ds.rf.isel(x=1, y=1).hvplot() * precipitation_events.isel(\n", " x=1, y=1, window=0\n", ").hvplot.scatter(color=\"red\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Daily precipitable water\n", "\n", "