Examples#

Simple Regridding#

To regrid a single Iris cube using an area-weighted conservative method:

import iris
from iris.experimental.ugrid import PARSE_UGRID_ON_LOAD
from esmf_regrid.schemes import ESMFAreaWeighted

# An example such a file can be found at:
# https://github.com/SciTools/iris-test-data/blob/master/test_data/NetCDF/unstructured_grid/data_C4.nc
with PARSE_UGRID_ON_LOAD.context():
    source_mesh_cube = iris.load_cube("mesh_cube.nc")

# An example of such a file can be found at:
# https://github.com/SciTools/iris-test-data/blob/master/test_data/NetCDF/global/xyt/SMALL_hires_wind_u_for_ipcc4.nc
target_grid_cube = iris.load_cube("grid_cube.nc")

result = source_mesh_cube.regrid(target_grid_cube, ESMFAreaWeighted())

Note that this scheme is flexible and it is also possible to regrid from a structured cube to an unstructured cube as follows:

result = target_grid_cube.regrid(source_mesh_cube, ESMFAreaWeighted())

Saving and Loading a Regridder#

A regridder can be set up for reuse, this saves time performing the computationally expensive initialisation process:

from esmf_regrid.schemes import ESMFAreaWeighted

# Initialise the regridder with a source mesh and target grid.
regridder = ESMFAreaWeighted().regridder(source_mesh_cube, target_grid_cube)

# use the initialised regridder to regrid the data from the source cube
# onto a cube with the same grid as `target_grid_cube`.
result = regridder(source_mesh_cube)

To make use of this efficiency across sessions, we support the saving of certain regridders. We can do this as follows:

from esmf_regrid.experimental.io import load_regridder, save_regridder

# Save the regridder.
save_regridder(regridder, "saved_regridder.nc")

# Load saved regridder.
loaded_regridder = load_regridder("saved_regridder.nc")

# Use loaded regridder.
result = loaded_regridder(source_mesh_cube)

Partitioning a Regridder#

Caution

The Partition class is experimental and there is no guarantee that the file structure will remain consistent and compatible in later versions.

If a regridder would be too large to handle in memory, it can be broken down into smaller regridders which can collectively do the job of the larger regridder. This is done using a Partition object.

Note

Currently, it is only possible to partition regridding when the source is a large grid and the target is small enough to fit in memory.

A Partition is made by specifying a source, a target, a list of files, and a way to divide the source grid into blocks whose regridders are saved to those files:

from iris.util import make_gridcube

from esmf_regrid import ESMFAreaWeighted
from esmf_regrid.experimental.partition import Partition

# Create a large source cube.
source_cube = make_gridcube(nx=800, ny=800)

# Create a small target cube.
target_cube = make_gridcube(nx=100, ny=100)

# Set the regridding scheme.
scheme = AreaWeighted()

# List a collection of file names/paths to save partial regridders to.
files = ["file_1", "file_2", "file_3", "file_4"]

# Set the size of each block of the partition. For the keyword `src_chunks`
# this follows the dask chunking API.
src_chunks = (400, 400)

# Initialise the partition.
partition = Partition(
    source_cube,
    target_cube,
    scheme,
    files,
    src_chunks=src_chunks
)

Note

there are several different ways of specifying the division of the source into blocks : see Partition.

Initialising the Partition will not generate the files automatically unless the auto_generate keyword is set to True. In order for this Partition to function, the regridder files must be generated by calling the generate_files method:

# Generate partial regridders and save them to the list of files.
partition.generate_files()

# Once the files have been generated, they can be used for regridding.
result = partition.apply_regridders(source_cube)

Note

Not all files need to be generated at once, if you have a grid which needs to be split into very many files, it is possible to generate only a portion of those files within a given session by passing the number of files to generate as an argument to the regridder. It is then possible to split the file generation in batches across multiple python sessions.

Once the files for a regridder have been generated, they can be used to reconstruct the partition object in a later session. This is done by passing in the list of files which have already been generated:

# Use the same arguments which constructed the original partition.
source_cube = make_gridcube(nx=800, ny=800)
target_cube = make_gridcube(nx=100, ny=100)
scheme = AreaWeighted()
files = ["file_1", "file_2", "file_3", "file_4"]
src_chunks = (400, 400)

# List the files which have already been generated.
saved_files = ["file_1", "file_2", "file_3", "file_4"]

# Reconstruct Partition from pre-generated files.
partition = Partition(
    source_cube,
    target_cube,
    scheme,
    files,
    src_chunks=src_chunks
    saved_files=saved_files  # Pass in the list of saved files.
)

# The new Partition can now be used without the need for generating files.
result = partition.apply_regridders(source_cube)