{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Comparison of seven regridding algorithms\n", "\n", "xESMF exposes seven different regridding algorithms from the ESMF library:\n", "\n", "- `bilinear`: `ESMF.RegridMethod.BILINEAR`\n", "- `conservative`: `ESMF.RegridMethod.CONSERVE`\n", "- `conservative_2nd`: `ESMF.RegridMethod.CONSERVE_2ND`\n", "- `conservative_normed`: `ESMF.RegridMethod.CONSERVE`\n", "- `patch`: `ESMF.RegridMethod.PATCH`\n", "- `nearest_s2d`: `ESMF.RegridMethod.NEAREST_STOD`\n", "- `nearest_d2s`: `ESMF.RegridMethod.NEAREST_DTOS`\n", "\n", "where `conservative_normed` is just the `conservative` method with the\n", "normalization set to `ESMF.NormType.FRACAREA` instead of the default\n", "`norm_type=ESMF.NormType.DSTAREA`.\n", "\n", "This notebook demonstrates how these algorithms behave in different situations.\n", "\n", "## Notes\n", "\n", "- `bilinear` and `conservative` should be the most commonly used methods. They\n", " are both monotonic (i.e. will not create new maximum/minimum).\n", "- `conservative_2nd` also requires cell bounds, but may overshoot source\n", " minimum/maximum values.\n", "- Nearest neighbour methods, either source to destination (s2d) or destination\n", " to source (d2s), could be useful in special cases. Keep in mind that d2s is\n", " highly non-monotonic.\n", "- Patch is ESMF's unique method, producing highly smooth results but quite slow.\n", "- From the ESMF documentation:\n", "\n", " > The weight $w_{ij}$ for a particular source cell $i$ and destination cell\n", " > $j$ are calculated as $w_{ij}=f_{ij} * A_{si}/A_{dj}$. In this equation\n", " > $f_{ij}$ is the fraction of the source cell $i$ contributing to destination\n", " > cell $j$, and $A_{si}$ and $A_{dj}$ are the areas of the source and\n", " > destination cells.\n", "\n", " For `conservative_normed`,\n", "\n", " > ... then the weights are further divided by the destination fraction. In\n", " > other words, in that case $w_{ij}=f_{ij} * A_{si}/(A_{dj}*D_j)$ where $D_j$\n", " > is fraction of the destination cell that intersects the unmasked source\n", " > grid.\n", "\n", "Detailed explanations are available on\n", "[ESMPy documentation](http://www.earthsystemmodeling.org/esmf_releases/last_built/esmpy_doc/html/api.html#regridding).\n", "\n", "## Preparation\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "import cartopy.crs as ccrs\n", "import numpy as np\n", "import xarray as xr\n", "import xesmf as xe\n", "\n", "method_list = [\n", " \"bilinear\",\n", " \"conservative\",\n", " \"conservative_2nd\",\n", " \"conservative_normed\",\n", " \"nearest_s2d\",\n", " \"nearest_d2s\",\n", " \"patch\",\n", "]" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "ds_in = xe.util.grid_global(20, 15) # input grid\n", "ds_fine = xe.util.grid_global(4, 4) # high-resolution target grid\n", "ds_coarse = xe.util.grid_global(30, 20) # low-resolution target grid" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make a wave field that is widely used in regridding benchmarks.\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
<xarray.Dataset> Size: 9kB\n",
"Dimensions: (y: 12, x: 18, y_b: 13, x_b: 19)\n",
"Coordinates:\n",
" lon (y, x) float64 2kB -170.0 -150.0 -130.0 ... 130.0 150.0 170.0\n",
" lat (y, x) float64 2kB -82.5 -82.5 -82.5 -82.5 ... 82.5 82.5 82.5 82.5\n",
" lon_b (y_b, x_b) float64 2kB -180.0 -160.0 -140.0 ... 140.0 160.0 180.0\n",
" lat_b (y_b, x_b) float64 2kB -90.0 -90.0 -90.0 -90.0 ... 90.0 90.0 90.0\n",
"Dimensions without coordinates: y, x, y_b, x_b\n",
"Data variables:\n",
" data (y, x) float64 2kB 2.016 2.009 1.997 1.987 ... 1.997 2.009 2.016