From 1f173b05a298c53294b6677cbb8490fb1998e3bc Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Tue, 10 Oct 2023 17:13:28 +0100 Subject: [PATCH 01/15] First pass at mesh to mesh --- .../experimental/unstructured_scheme.py | 91 +++++++ esmf_regrid/schemes.py | 68 +++++- ...est_regrid_unstructured_to_unstructured.py | 223 ++++++++++++++++++ .../unit/schemes/test_ESMFAreaWeighted.py | 2 +- .../tests/unit/schemes/test_ESMFBilinear.py | 2 +- .../tests/unit/schemes/test_ESMFNearest.py | 2 +- 6 files changed, 381 insertions(+), 7 deletions(-) create mode 100644 esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py diff --git a/esmf_regrid/experimental/unstructured_scheme.py b/esmf_regrid/experimental/unstructured_scheme.py index f17aadcd..2eda00e6 100644 --- a/esmf_regrid/experimental/unstructured_scheme.py +++ b/esmf_regrid/experimental/unstructured_scheme.py @@ -353,3 +353,94 @@ def __init__( self.resolution = src_resolution self.mesh, self.location = self._tgt self.grid_x, self.grid_y = self._src + + +def regrid_unstructured_to_unstructured( + src_mesh_cube, + tgt_mesh_cube, + mdtol=0, + method="conservative", + src_resolution=None, + use_src_mask=False, + use_tgt_mask=False, +): + r""" + Regrid rectilinear :class:`~iris.cube.Cube` onto unstructured mesh. + + Return a new :class:`~iris.cube.Cube` with :attr:`~iris.cube.Cube.data` + values calculated using weights generated by :mod:`esmpy` to give the weighted + mean of :attr:`~iris.cube.Cube.data` values from ``src_cube`` regridded onto the + horizontal mesh of ``mesh_cube``. The dimensions on the :class:`~iris.cube.Cube` associated + with the grid will be replaced by a dimension associated with the + :attr:`~iris.cube.Cube.mesh`. + That dimension will be the first of the grid dimensions, whether + it is associated with the ``x`` or ``y`` coordinate. Since two dimensions are + being replaced by one, coordinates associated with dimensions after + the grid will become associated with dimensions one lower. + This function requires that the horizontal dimension of ``mesh_cube`` is + described by a 2D mesh with data located on the faces of that mesh + for conservative regridding and located on either faces or nodes for + bilinear regridding. + This function allows the horizontal grid of ``grid_cube`` to be either + rectilinear or curvilinear (i.e. expressed in terms of two orthogonal + 1D coordinates or via a pair of 2D coordinates). + This function also requires that the :class:`~iris.coords.Coord`\\ s describing the + horizontal grid have :attr:`~iris.coords.Coord.bounds`. + + Parameters + ---------- + src_cube : :class:`iris.cube.Cube` + A rectilinear instance of :class:`~iris.cube.Cube` that supplies the data, + metadata and coordinates. + mesh_cube : :class:`iris.cube.Cube` + An unstructured instance of :class:`~iris.cube.Cube` that supplies the desired + horizontal mesh definition. + mdtol : float, default=0 + Tolerance of missing data. The value returned in each element of the + returned :class:`~iris.cube.Cube`\\ 's :attr:`~iris.cube.Cube.data` array + will be masked if the fraction of masked + data in the overlapping cells of the source cube exceeds ``mdtol``. This + fraction is calculated based on the area of masked cells within each + target cell. ``mdtol=0`` means no missing data is tolerated while ``mdtol=1`` + will mean the resulting element will be masked if and only if all the + overlapping cells of the ``src_cube`` are masked. + method : str, default="conservative" + Either "conservative", "bilinear" or "nearest". Corresponds to the :mod:`esmpy` methods + :attr:`~esmpy.api.constants.RegridMethod.CONSERVE` or + :attr:`~esmpy.api.constants.RegridMethod.BILINEAR` or + :attr:`~esmpy.api.constants.RegridMethod.NEAREST` used to calculate weights. + src_resolution : int, optional + If present, represents the amount of latitude slices per cell + given to ESMF for calculation. + use_src_mask : :obj:`~numpy.typing.ArrayLike` or bool, default=False + Either an array representing the cells in the source to ignore, or else + a boolean value. If True, this array is taken from the mask on the data + in ``src_cube``. If False, no mask will be taken and all points will + be used in weights calculation. + use_tgt_mask : :obj:`~numpy.typing.ArrayLike` or bool, default=False + Either an array representing the cells in the target to ignore, or else + a boolean value. If True, this array is taken from the mask on the data + in ``grid_cube``. If False, no mask will be taken and all points + will be used in weights calculation. + + Returns + ------- + :class:`iris.cube.Cube` + A new :class:`~iris.cube.Cube` instance. + + """ + if tgt_mesh_cube.mesh is None: + raise ValueError("mesh_cube has no mesh.") + src_mask = _get_mask(src_mesh_cube, use_src_mask) + tgt_mask = _get_mask(tgt_mesh_cube, use_tgt_mask) + + regrid_info = _regrid_rectilinear_to_unstructured__prepare( + src_mesh_cube, + tgt_mesh_cube, + method=method, + src_resolution=src_resolution, + src_mask=src_mask, + tgt_mask=tgt_mask, + ) + result = _regrid_rectilinear_to_unstructured__perform(src_mesh_cube, regrid_info, mdtol) + return result diff --git a/esmf_regrid/schemes.py b/esmf_regrid/schemes.py index 21731830..ef5e60ac 100644 --- a/esmf_regrid/schemes.py +++ b/esmf_regrid/schemes.py @@ -769,17 +769,77 @@ def _regrid_rectilinear_to_unstructured__perform(src_cube, regrid_info, mdtol): def _regrid_unstructured_to_unstructured__prepare( - src_grid_cube, - target_mesh_cube, + src_mesh_cube, + tgt_cube_or_mesh, method, precomputed_weights=None, + src_mask=None, + tgt_mask=None, tgt_location=None, ): - raise NotImplementedError + + if isinstance(tgt_cube_or_mesh, Mesh): + mesh = tgt_cube_or_mesh + location = tgt_location + else: + mesh = tgt_cube_or_mesh.mesh + location = tgt_cube_or_mesh.location + + mesh_dim = src_mesh_cube.mesh_dim() + + src_meshinfo = _make_meshinfo(src_mesh_cube, method, src_mask, "source") + tgt_meshinfo = _make_meshinfo(tgt_cube_or_mesh, method, tgt_mask, "target", location=tgt_location) + + regridder = Regridder( + src_meshinfo, tgt_meshinfo, method=method, precomputed_weights=precomputed_weights + ) + + regrid_info = RegridInfo( + dims=[mesh_dim], + target=MeshRecord(mesh, location), + regridder=regridder, + ) + + return regrid_info def _regrid_unstructured_to_unstructured__perform(src_cube, regrid_info, mdtol): - raise NotImplementedError + + (mesh_dim,) = regrid_info.dims + mesh, location = regrid_info.target + regridder = regrid_info.regridder + + regrid = functools.partial( + _regrid_along_dims, + regridder, + dims=[mesh_dim], + num_out_dims=1, + mdtol=mdtol, + ) + if location =="face": + face_node = mesh.face_node_connectivity + chunk_shape = (face_node.shape[face_node.location_axis],) + elif location == "node": + chunk_shape = mesh.node_coords[0].shape + else: + raise NotImplementedError(f"Unrecognised location {location}.") + + new_data = _map_complete_blocks( + src_cube, + regrid, + (mesh_dim,), + chunk_shape, + ) + + new_cube = _create_cube( + new_data, + src_cube, + (mesh_dim,), + mesh.to_MeshCoords(location), + 1, + ) + + return new_cube def regrid_rectilinear_to_rectilinear( diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py new file mode 100644 index 00000000..0ae77c7b --- /dev/null +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -0,0 +1,223 @@ +"""Unit tests for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_unstructured_to_unstructured`.""" + +from iris.coords import AuxCoord, DimCoord +from iris.cube import Cube +import numpy as np +import pytest + +from esmf_regrid.experimental.unstructured_scheme import ( + regrid_unstructured_to_unstructured, +) +from esmf_regrid.tests.unit.schemes.test__cube_to_MeshInfo import ( + _gridlike_mesh_cube, +) +from esmf_regrid.tests.unit.schemes.test__mesh_to_MeshInfo import ( + _gridlike_mesh_cube, +) +from esmf_regrid.tests.unit.schemes.test__regrid_unstructured_to_unstructured__prepare import ( + _flat_mesh_cube, + _full_mesh, +) + + +def _add_metadata(cube): + result = cube.copy() + result.units = "K" + result.attributes = {"a": 1} + result.standard_name = "air_temperature" + scalar_height = AuxCoord([5], units="m", standard_name="height") + scalar_time = DimCoord([10], units="s", standard_name="time") + result.add_aux_coord(scalar_height) + result.add_aux_coord(scalar_time) + return result + + +def test_flat_cubes(): + """ + Basic test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_unstructured_to_unstructured`. + + Tests with flat cubes as input (a 1D mesh cube and a 2D grid cube). + """ + src = _flat_mesh_cube() + + n_lons = 6 + n_lats = 5 + lon_bounds = (-180, 180) + lat_bounds = (-90, 90) + tgt = _flat_mesh_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) + # Ensure data in the target grid is different to the expected data. + # i.e. target grid data is all zero, expected data is all one + tgt.data[:] = 0 + + src = _add_metadata(src) + src.data[:] = 1 # Ensure all data in the source is one. + result = regrid_unstructured_to_unstructured(src, tgt) + + expected_data = np.ones([n_lats, n_lons]) + expected_cube = _add_metadata(tgt) + + # Lenient check for data. + assert np.allclose(expected_data, result.data) + + # Check metadata and scalar coords. + expected_cube.data = result.data + assert expected_cube == result + + +@pytest.mark.parametrize("method", ("bilinear", "nearest")) +def test_node_friendly_methods(method): + """ + Basic test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_unstructured_to_unstructured`. + + Tests with the bilinear and nearest method. + """ + n_lons = 6 + n_lats = 5 + lon_bounds = (-180, 180) + lat_bounds = (-90, 90) + src = _gridlike_mesh_cube(n_lons, n_lats, location="node") + tgt = _gridlike_mesh_cube(n_lons, n_lats, location="node") + # Ensure data in the target mesh is different to the expected data. + # i.e. target mesh data is all zero, expected data is all one + tgt.data[:] = 0 + + src = _add_metadata(src) + src.data[:] = 1 # Ensure all data in the source is one. + result = regrid_unstructured_to_unstructured(src, tgt, method=method) + + expected_data = np.ones(tgt.data) + expected_cube = _add_metadata(tgt) + + # Lenient check for data. + assert np.allclose(expected_data, result.data) + + # Check metadata and scalar coords. + expected_cube.data = result.data + assert expected_cube == result + + +def test_invalid_args(): + """ + Test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_unstructured_to_unstructured`. + + Tests that an appropriate error is raised when arguments are invalid. + """ + n_lons = 6 + n_lats = 5 + lon_bounds = (-180, 180) + lat_bounds = (-90, 90) + node_src = _gridlike_mesh_cube(n_lons, n_lats, location="node") + edge_src = _gridlike_mesh_cube(n_lons, n_lats, location="edge") + face_src = _gridlike_mesh_cube(n_lons, n_lats, location="face") + tgt = _gridlike_mesh_cube(n_lons, n_lats) + + with pytest.raises(ValueError): + _ = regrid_unstructured_to_unstructured(tgt, tgt, method="bilinear") + with pytest.raises(NotImplementedError): + _ = regrid_unstructured_to_unstructured(face_src, tgt, method="other") + with pytest.raises(ValueError) as excinfo: + _ = regrid_unstructured_to_unstructured(node_src, tgt, method="conservative") + expected_message = ( + "Conservative regridding requires a source cube located on " + "the face of a cube, target cube had the node location." + ) + assert expected_message in str(excinfo.value) + with pytest.raises(ValueError) as excinfo: + _ = regrid_unstructured_to_unstructured(edge_src, tgt, method="bilinear") + expected_message = ( + "bilinear regridding requires a source cube with a node " + "or face location, target cube had the edge location." + ) + assert expected_message in str(excinfo.value) + with pytest.raises(ValueError) as excinfo: + _ = regrid_unstructured_to_unstructured(edge_src, tgt, method="nearest") + expected_message = ( + "nearest regridding requires a source cube with a node " + "or face location, target cube had the edge location." + ) + assert expected_message in str(excinfo.value) + + +def test_multidim_cubes(): + """ + Test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_unstructured_to_unstructured`. + + Tests with multidimensional cubes. The source cube contains + coordinates on the dimensions before and after the mesh dimension. + """ + tgt = _flat_mesh_cube() + tgt_mesh = tgt.mesh + mesh = _full_mesh() + mesh_length = mesh.connectivity(contains_face=True).shape[0] + tgt_mesh_length = mesh.connectivity(contains_face=True).shape[0] + + h = 2 + t = 3 + height = DimCoord(np.arange(h), standard_name="height") + time = DimCoord(np.arange(t), standard_name="time") + + src_data = np.empty([t, mesh_length, h]) + src_data[:] = np.arange(t * h).reshape([t, h])[:, np.newaxis, :] + cube = Cube(src_data) + mesh_coord_x, mesh_coord_y = mesh.to_MeshCoords("face") + cube.add_aux_coord(mesh_coord_x, 1) + cube.add_aux_coord(mesh_coord_y, 1) + cube.add_dim_coord(time, 0) + cube.add_dim_coord(height, 2) + + n_lons = 6 + n_lats = 5 + lon_bounds = (-180, 180) + lat_bounds = (-90, 90) + tgt = _gridlike_mesh_cube(n_lons, n_lats) + + result = regrid_unstructured_to_unstructured(cube, tgt) + + # Lenient check for data. + expected_data = np.empty([t, n_lats, n_lons, h]) + expected_data[:] = np.arange(t * h).reshape(t, h)[:, np.newaxis, np.newaxis, :] + assert np.allclose(expected_data, result.data) + + expected_cube = Cube(expected_data) + expected_cube.add_dim_coord(time, 0) + expected_cube.add_dim_coord(tgt.coord("latitude"), 1) + expected_cube.add_dim_coord(tgt.coord("longitude"), 2) + expected_cube.add_dim_coord(height, 3) + + # Check metadata and scalar coords. + result.data = expected_data + assert expected_cube == result + + +def test_resolution(): + """ + Basic test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_unstructured_to_unstructured`. + + Tests the tgt_resolution keyword with grids that would otherwise not work. + """ + src = _flat_mesh_cube() + + # The resulting grid has full latitude bounds and cells must be split up. + n_lons = 1 + n_lats = 5 + lon_bounds = (-180, 180) + lat_bounds = (-90, 90) + tgt = _gridlike_mesh_cube(n_lons, n_lats) + # Ensure data in the target grid is different to the expected data. + # i.e. target grid data is all zero, expected data is all one + tgt.data[:] = 0 + + src = _add_metadata(src) + src.data[:] = 1 # Ensure all data in the source is one. + result = regrid_unstructured_to_unstructured(src, tgt, tgt_resolution=8) + + expected_data = np.ones([n_lats, n_lons]) + expected_cube = _add_metadata(tgt) + + # Lenient check for data. + # Note that when tgt_resolution=None, this would be a fully masked array. + assert np.allclose(expected_data, result.data) + + # Check metadata and scalar coords. + expected_cube.data = result.data + assert expected_cube == result diff --git a/esmf_regrid/tests/unit/schemes/test_ESMFAreaWeighted.py b/esmf_regrid/tests/unit/schemes/test_ESMFAreaWeighted.py index e9986a74..c276bf84 100644 --- a/esmf_regrid/tests/unit/schemes/test_ESMFAreaWeighted.py +++ b/esmf_regrid/tests/unit/schemes/test_ESMFAreaWeighted.py @@ -14,7 +14,7 @@ @pytest.mark.parametrize( "src_type,tgt_type", - [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid")], + [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid"), ("mesh", "mesh")], ) def test_cube_regrid(src_type, tgt_type): """ diff --git a/esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py b/esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py index d92350bf..c7bb34ac 100644 --- a/esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py +++ b/esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py @@ -14,7 +14,7 @@ @pytest.mark.parametrize( "src_type,tgt_type", - [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid")], + [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid"), ("mesh", "mesh")], ) def test_cube_regrid(src_type, tgt_type): """ diff --git a/esmf_regrid/tests/unit/schemes/test_ESMFNearest.py b/esmf_regrid/tests/unit/schemes/test_ESMFNearest.py index 85f8ec49..9d381f54 100644 --- a/esmf_regrid/tests/unit/schemes/test_ESMFNearest.py +++ b/esmf_regrid/tests/unit/schemes/test_ESMFNearest.py @@ -19,7 +19,7 @@ @pytest.mark.parametrize( "src_type,tgt_type", - [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid")], + [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid"), ("mesh", "mesh")], ) def test_cube_regrid(src_type, tgt_type): """ From 6e4c2087cfc5a95b0cb1a957c35b8b8e1086e0a0 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Tue, 10 Oct 2023 17:30:57 +0100 Subject: [PATCH 02/15] fix tests #1 --- .../test_regrid_unstructured_to_unstructured.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index 0ae77c7b..a0df4e8c 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -8,13 +8,10 @@ from esmf_regrid.experimental.unstructured_scheme import ( regrid_unstructured_to_unstructured, ) -from esmf_regrid.tests.unit.schemes.test__cube_to_MeshInfo import ( - _gridlike_mesh_cube, -) from esmf_regrid.tests.unit.schemes.test__mesh_to_MeshInfo import ( _gridlike_mesh_cube, ) -from esmf_regrid.tests.unit.schemes.test__regrid_unstructured_to_unstructured__prepare import ( +from esmf_regrid.tests.unit.schemes.test__regrid_unstructured_to_rectilinear__prepare import ( _flat_mesh_cube, _full_mesh, ) From 41ea610abfe31c654288478f7eea9b1f24debe0d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:18:10 +0000 Subject: [PATCH 03/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- esmf_regrid/experimental/unstructured_scheme.py | 4 +++- esmf_regrid/schemes.py | 13 ++++++++----- .../tests/unit/schemes/test_ESMFAreaWeighted.py | 8 +++++++- esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py | 8 +++++++- esmf_regrid/tests/unit/schemes/test_ESMFNearest.py | 8 +++++++- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/esmf_regrid/experimental/unstructured_scheme.py b/esmf_regrid/experimental/unstructured_scheme.py index 2eda00e6..b1d1efd2 100644 --- a/esmf_regrid/experimental/unstructured_scheme.py +++ b/esmf_regrid/experimental/unstructured_scheme.py @@ -442,5 +442,7 @@ def regrid_unstructured_to_unstructured( src_mask=src_mask, tgt_mask=tgt_mask, ) - result = _regrid_rectilinear_to_unstructured__perform(src_mesh_cube, regrid_info, mdtol) + result = _regrid_rectilinear_to_unstructured__perform( + src_mesh_cube, regrid_info, mdtol + ) return result diff --git a/esmf_regrid/schemes.py b/esmf_regrid/schemes.py index ef5e60ac..654af4f1 100644 --- a/esmf_regrid/schemes.py +++ b/esmf_regrid/schemes.py @@ -777,7 +777,6 @@ def _regrid_unstructured_to_unstructured__prepare( tgt_mask=None, tgt_location=None, ): - if isinstance(tgt_cube_or_mesh, Mesh): mesh = tgt_cube_or_mesh location = tgt_location @@ -788,10 +787,15 @@ def _regrid_unstructured_to_unstructured__prepare( mesh_dim = src_mesh_cube.mesh_dim() src_meshinfo = _make_meshinfo(src_mesh_cube, method, src_mask, "source") - tgt_meshinfo = _make_meshinfo(tgt_cube_or_mesh, method, tgt_mask, "target", location=tgt_location) + tgt_meshinfo = _make_meshinfo( + tgt_cube_or_mesh, method, tgt_mask, "target", location=tgt_location + ) regridder = Regridder( - src_meshinfo, tgt_meshinfo, method=method, precomputed_weights=precomputed_weights + src_meshinfo, + tgt_meshinfo, + method=method, + precomputed_weights=precomputed_weights, ) regrid_info = RegridInfo( @@ -804,7 +808,6 @@ def _regrid_unstructured_to_unstructured__prepare( def _regrid_unstructured_to_unstructured__perform(src_cube, regrid_info, mdtol): - (mesh_dim,) = regrid_info.dims mesh, location = regrid_info.target regridder = regrid_info.regridder @@ -816,7 +819,7 @@ def _regrid_unstructured_to_unstructured__perform(src_cube, regrid_info, mdtol): num_out_dims=1, mdtol=mdtol, ) - if location =="face": + if location == "face": face_node = mesh.face_node_connectivity chunk_shape = (face_node.shape[face_node.location_axis],) elif location == "node": diff --git a/esmf_regrid/tests/unit/schemes/test_ESMFAreaWeighted.py b/esmf_regrid/tests/unit/schemes/test_ESMFAreaWeighted.py index c276bf84..e73bee5d 100644 --- a/esmf_regrid/tests/unit/schemes/test_ESMFAreaWeighted.py +++ b/esmf_regrid/tests/unit/schemes/test_ESMFAreaWeighted.py @@ -14,7 +14,13 @@ @pytest.mark.parametrize( "src_type,tgt_type", - [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid"), ("mesh", "mesh")], + [ + ("grid", "grid"), + ("grid", "mesh"), + ("grid", "just_mesh"), + ("mesh", "grid"), + ("mesh", "mesh"), + ], ) def test_cube_regrid(src_type, tgt_type): """ diff --git a/esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py b/esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py index c7bb34ac..393bbe0a 100644 --- a/esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py +++ b/esmf_regrid/tests/unit/schemes/test_ESMFBilinear.py @@ -14,7 +14,13 @@ @pytest.mark.parametrize( "src_type,tgt_type", - [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid"), ("mesh", "mesh")], + [ + ("grid", "grid"), + ("grid", "mesh"), + ("grid", "just_mesh"), + ("mesh", "grid"), + ("mesh", "mesh"), + ], ) def test_cube_regrid(src_type, tgt_type): """ diff --git a/esmf_regrid/tests/unit/schemes/test_ESMFNearest.py b/esmf_regrid/tests/unit/schemes/test_ESMFNearest.py index 9d381f54..b5812b5a 100644 --- a/esmf_regrid/tests/unit/schemes/test_ESMFNearest.py +++ b/esmf_regrid/tests/unit/schemes/test_ESMFNearest.py @@ -19,7 +19,13 @@ @pytest.mark.parametrize( "src_type,tgt_type", - [("grid", "grid"), ("grid", "mesh"), ("grid", "just_mesh"), ("mesh", "grid"), ("mesh", "mesh")], + [ + ("grid", "grid"), + ("grid", "mesh"), + ("grid", "just_mesh"), + ("mesh", "grid"), + ("mesh", "mesh"), + ], ) def test_cube_regrid(src_type, tgt_type): """ From d9f46d920ac0e50c837f3b7d0e1b4b1fb9236b40 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Wed, 11 Oct 2023 12:32:26 +0100 Subject: [PATCH 04/15] remve resolution and correct ref's --- .../experimental/unstructured_scheme.py | 8 ++--- ...est_regrid_unstructured_to_unstructured.py | 34 ------------------- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/esmf_regrid/experimental/unstructured_scheme.py b/esmf_regrid/experimental/unstructured_scheme.py index b1d1efd2..95a00b45 100644 --- a/esmf_regrid/experimental/unstructured_scheme.py +++ b/esmf_regrid/experimental/unstructured_scheme.py @@ -9,6 +9,8 @@ _regrid_rectilinear_to_unstructured__prepare, _regrid_unstructured_to_rectilinear__perform, _regrid_unstructured_to_rectilinear__prepare, + _regrid_unstructured_to_unstructured__perform, + _regrid_unstructured_to_unstructured__prepare, ) @@ -360,7 +362,6 @@ def regrid_unstructured_to_unstructured( tgt_mesh_cube, mdtol=0, method="conservative", - src_resolution=None, use_src_mask=False, use_tgt_mask=False, ): @@ -434,15 +435,14 @@ def regrid_unstructured_to_unstructured( src_mask = _get_mask(src_mesh_cube, use_src_mask) tgt_mask = _get_mask(tgt_mesh_cube, use_tgt_mask) - regrid_info = _regrid_rectilinear_to_unstructured__prepare( + regrid_info = _regrid_unstructured_to_unstructured__prepare( src_mesh_cube, tgt_mesh_cube, method=method, - src_resolution=src_resolution, src_mask=src_mask, tgt_mask=tgt_mask, ) - result = _regrid_rectilinear_to_unstructured__perform( + result = _regrid_unstructured_to_unstructured__perform( src_mesh_cube, regrid_info, mdtol ) return result diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index a0df4e8c..9bbb1d9b 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -184,37 +184,3 @@ def test_multidim_cubes(): # Check metadata and scalar coords. result.data = expected_data assert expected_cube == result - - -def test_resolution(): - """ - Basic test for :func:`esmf_regrid.experimental.unstructured_scheme.regrid_unstructured_to_unstructured`. - - Tests the tgt_resolution keyword with grids that would otherwise not work. - """ - src = _flat_mesh_cube() - - # The resulting grid has full latitude bounds and cells must be split up. - n_lons = 1 - n_lats = 5 - lon_bounds = (-180, 180) - lat_bounds = (-90, 90) - tgt = _gridlike_mesh_cube(n_lons, n_lats) - # Ensure data in the target grid is different to the expected data. - # i.e. target grid data is all zero, expected data is all one - tgt.data[:] = 0 - - src = _add_metadata(src) - src.data[:] = 1 # Ensure all data in the source is one. - result = regrid_unstructured_to_unstructured(src, tgt, tgt_resolution=8) - - expected_data = np.ones([n_lats, n_lons]) - expected_cube = _add_metadata(tgt) - - # Lenient check for data. - # Note that when tgt_resolution=None, this would be a fully masked array. - assert np.allclose(expected_data, result.data) - - # Check metadata and scalar coords. - expected_cube.data = result.data - assert expected_cube == result From a94f12346f8f076e9089716dc2b766c20063bf84 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Wed, 11 Oct 2023 12:57:08 +0100 Subject: [PATCH 05/15] remove circular --- .../test_regrid_unstructured_to_unstructured.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index 9bbb1d9b..05843ac9 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -39,9 +39,7 @@ def test_flat_cubes(): n_lons = 6 n_lats = 5 - lon_bounds = (-180, 180) - lat_bounds = (-90, 90) - tgt = _flat_mesh_cube(n_lons, n_lats, lon_bounds, lat_bounds, circular=True) + tgt = _flat_mesh_cube() # Ensure data in the target grid is different to the expected data. # i.e. target grid data is all zero, expected data is all one tgt.data[:] = 0 @@ -70,8 +68,6 @@ def test_node_friendly_methods(method): """ n_lons = 6 n_lats = 5 - lon_bounds = (-180, 180) - lat_bounds = (-90, 90) src = _gridlike_mesh_cube(n_lons, n_lats, location="node") tgt = _gridlike_mesh_cube(n_lons, n_lats, location="node") # Ensure data in the target mesh is different to the expected data. @@ -101,8 +97,6 @@ def test_invalid_args(): """ n_lons = 6 n_lats = 5 - lon_bounds = (-180, 180) - lat_bounds = (-90, 90) node_src = _gridlike_mesh_cube(n_lons, n_lats, location="node") edge_src = _gridlike_mesh_cube(n_lons, n_lats, location="edge") face_src = _gridlike_mesh_cube(n_lons, n_lats, location="face") @@ -164,8 +158,6 @@ def test_multidim_cubes(): n_lons = 6 n_lats = 5 - lon_bounds = (-180, 180) - lat_bounds = (-90, 90) tgt = _gridlike_mesh_cube(n_lons, n_lats) result = regrid_unstructured_to_unstructured(cube, tgt) From 2e9cfdfaa1672af153c798f539b9897e6da26af9 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Wed, 11 Oct 2023 15:58:55 +0100 Subject: [PATCH 06/15] new changes to fix tests --- esmf_regrid/schemes.py | 3 ++- .../test_regrid_unstructured_to_unstructured.py | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/esmf_regrid/schemes.py b/esmf_regrid/schemes.py index 654af4f1..b5f9d4f1 100644 --- a/esmf_regrid/schemes.py +++ b/esmf_regrid/schemes.py @@ -775,6 +775,7 @@ def _regrid_unstructured_to_unstructured__prepare( precomputed_weights=None, src_mask=None, tgt_mask=None, + src_location=None, tgt_location=None, ): if isinstance(tgt_cube_or_mesh, Mesh): @@ -786,7 +787,7 @@ def _regrid_unstructured_to_unstructured__prepare( mesh_dim = src_mesh_cube.mesh_dim() - src_meshinfo = _make_meshinfo(src_mesh_cube, method, src_mask, "source") + src_meshinfo = _make_meshinfo(src_mesh_cube, method, src_location, src_mask, "source") tgt_meshinfo = _make_meshinfo( tgt_cube_or_mesh, method, tgt_mask, "target", location=tgt_location ) diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index 05843ac9..605be1f0 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -102,8 +102,6 @@ def test_invalid_args(): face_src = _gridlike_mesh_cube(n_lons, n_lats, location="face") tgt = _gridlike_mesh_cube(n_lons, n_lats) - with pytest.raises(ValueError): - _ = regrid_unstructured_to_unstructured(tgt, tgt, method="bilinear") with pytest.raises(NotImplementedError): _ = regrid_unstructured_to_unstructured(face_src, tgt, method="other") with pytest.raises(ValueError) as excinfo: @@ -163,7 +161,7 @@ def test_multidim_cubes(): result = regrid_unstructured_to_unstructured(cube, tgt) # Lenient check for data. - expected_data = np.empty([t, n_lats, n_lons, h]) + expected_data = np.empty([t, n_lats * n_lons, h]) expected_data[:] = np.arange(t * h).reshape(t, h)[:, np.newaxis, np.newaxis, :] assert np.allclose(expected_data, result.data) From d6bf2a3c13b17b635af604db3d3d2251183ae419 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Thu, 12 Oct 2023 10:08:53 +0100 Subject: [PATCH 07/15] test fix --- .../test_regrid_unstructured_to_unstructured.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index 605be1f0..aa6105de 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -78,7 +78,7 @@ def test_node_friendly_methods(method): src.data[:] = 1 # Ensure all data in the source is one. result = regrid_unstructured_to_unstructured(src, tgt, method=method) - expected_data = np.ones(tgt.data) + expected_data = np.ones_like(tgt.data) expected_cube = _add_metadata(tgt) # Lenient check for data. @@ -162,7 +162,7 @@ def test_multidim_cubes(): # Lenient check for data. expected_data = np.empty([t, n_lats * n_lons, h]) - expected_data[:] = np.arange(t * h).reshape(t, h)[:, np.newaxis, np.newaxis, :] + expected_data[:] = np.arange(t * h).reshape(t, h)[:, np.newaxis, :] assert np.allclose(expected_data, result.data) expected_cube = Cube(expected_data) From e3968dda495d20adc4c48f868fda0e721a498728 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:59:11 +0000 Subject: [PATCH 08/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- esmf_regrid/schemes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esmf_regrid/schemes.py b/esmf_regrid/schemes.py index b5f9d4f1..eed324b6 100644 --- a/esmf_regrid/schemes.py +++ b/esmf_regrid/schemes.py @@ -787,7 +787,9 @@ def _regrid_unstructured_to_unstructured__prepare( mesh_dim = src_mesh_cube.mesh_dim() - src_meshinfo = _make_meshinfo(src_mesh_cube, method, src_location, src_mask, "source") + src_meshinfo = _make_meshinfo( + src_mesh_cube, method, src_location, src_mask, "source" + ) tgt_meshinfo = _make_meshinfo( tgt_cube_or_mesh, method, tgt_mask, "target", location=tgt_location ) From 04b9ca8d898a78afacb7e82bccc903e7adf11540 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Mon, 30 Oct 2023 12:06:21 +0000 Subject: [PATCH 09/15] fix test --- .../test_regrid_unstructured_to_unstructured.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index aa6105de..fca795d2 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -134,11 +134,9 @@ def test_multidim_cubes(): Tests with multidimensional cubes. The source cube contains coordinates on the dimensions before and after the mesh dimension. """ - tgt = _flat_mesh_cube() - tgt_mesh = tgt.mesh + mesh = _full_mesh() mesh_length = mesh.connectivity(contains_face=True).shape[0] - tgt_mesh_length = mesh.connectivity(contains_face=True).shape[0] h = 2 t = 3 From bac8070ddbd1eb1da73ad97d74898ee718f146bb Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Mon, 30 Oct 2023 16:58:48 +0000 Subject: [PATCH 10/15] test fixes --- esmf_regrid/schemes.py | 2 +- .../test_regrid_unstructured_to_unstructured.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esmf_regrid/schemes.py b/esmf_regrid/schemes.py index eed324b6..a1cdc81b 100644 --- a/esmf_regrid/schemes.py +++ b/esmf_regrid/schemes.py @@ -788,7 +788,7 @@ def _regrid_unstructured_to_unstructured__prepare( mesh_dim = src_mesh_cube.mesh_dim() src_meshinfo = _make_meshinfo( - src_mesh_cube, method, src_location, src_mask, "source" + src_mesh_cube, method, src_mask, "source", location=src_location ) tgt_meshinfo = _make_meshinfo( tgt_cube_or_mesh, method, tgt_mask, "target", location=tgt_location diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index fca795d2..b529b97b 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -165,8 +165,8 @@ def test_multidim_cubes(): expected_cube = Cube(expected_data) expected_cube.add_dim_coord(time, 0) - expected_cube.add_dim_coord(tgt.coord("latitude"), 1) - expected_cube.add_dim_coord(tgt.coord("longitude"), 2) + expected_cube.add_aux_coord(tgt.coord("latitude"), 1) + expected_cube.add_aux_coord(tgt.coord("longitude"), 2) expected_cube.add_dim_coord(height, 3) # Check metadata and scalar coords. From 5ff937eb0ebfc3a9edcaf1b9a786d7827bdc8eff Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Mon, 30 Oct 2023 17:11:48 +0000 Subject: [PATCH 11/15] match cube dimension --- .../test_regrid_unstructured_to_unstructured.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index b529b97b..634c7a94 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -148,7 +148,7 @@ def test_multidim_cubes(): cube = Cube(src_data) mesh_coord_x, mesh_coord_y = mesh.to_MeshCoords("face") cube.add_aux_coord(mesh_coord_x, 1) - cube.add_aux_coord(mesh_coord_y, 1) + cube.add_aux_coord(mesh_coord_y, 2) cube.add_dim_coord(time, 0) cube.add_dim_coord(height, 2) From 3cc1e28a48fadec96ab8c937a745026c11c696f5 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Thu, 2 Nov 2023 10:08:46 +0000 Subject: [PATCH 12/15] fixing last test --- .../test_regrid_unstructured_to_unstructured.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index 634c7a94..8c01754f 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -148,7 +148,7 @@ def test_multidim_cubes(): cube = Cube(src_data) mesh_coord_x, mesh_coord_y = mesh.to_MeshCoords("face") cube.add_aux_coord(mesh_coord_x, 1) - cube.add_aux_coord(mesh_coord_y, 2) + cube.add_aux_coord(mesh_coord_y, 1) cube.add_dim_coord(time, 0) cube.add_dim_coord(height, 2) @@ -166,7 +166,7 @@ def test_multidim_cubes(): expected_cube = Cube(expected_data) expected_cube.add_dim_coord(time, 0) expected_cube.add_aux_coord(tgt.coord("latitude"), 1) - expected_cube.add_aux_coord(tgt.coord("longitude"), 2) + expected_cube.add_aux_coord(tgt.coord("longitude"), 1) expected_cube.add_dim_coord(height, 3) # Check metadata and scalar coords. From ece7799659931bb2cdb63c1e6a75b8dc5f405f0a Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Thu, 2 Nov 2023 10:34:46 +0000 Subject: [PATCH 13/15] all tests fixed --- .../test_regrid_unstructured_to_unstructured.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py index 8c01754f..8be55fe9 100644 --- a/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py +++ b/esmf_regrid/tests/unit/experimental/unstructured_scheme/test_regrid_unstructured_to_unstructured.py @@ -167,7 +167,7 @@ def test_multidim_cubes(): expected_cube.add_dim_coord(time, 0) expected_cube.add_aux_coord(tgt.coord("latitude"), 1) expected_cube.add_aux_coord(tgt.coord("longitude"), 1) - expected_cube.add_dim_coord(height, 3) + expected_cube.add_dim_coord(height, 2) # Check metadata and scalar coords. result.data = expected_data From e9de3a2dd45d81742b010176af26c259b9292b00 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Thu, 2 Nov 2023 16:05:45 +0000 Subject: [PATCH 14/15] adding and updating docstrings --- .../experimental/unstructured_scheme.py | 9 +++---- esmf_regrid/schemes.py | 26 +++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/esmf_regrid/experimental/unstructured_scheme.py b/esmf_regrid/experimental/unstructured_scheme.py index 95a00b45..e6562ac0 100644 --- a/esmf_regrid/experimental/unstructured_scheme.py +++ b/esmf_regrid/experimental/unstructured_scheme.py @@ -390,10 +390,10 @@ def regrid_unstructured_to_unstructured( Parameters ---------- - src_cube : :class:`iris.cube.Cube` - A rectilinear instance of :class:`~iris.cube.Cube` that supplies the data, + src_mesh_cube : :class:`iris.cube.Cube` + A unstructured instance of :class:`~iris.cube.Cube` that supplies the data, metadata and coordinates. - mesh_cube : :class:`iris.cube.Cube` + tgt_mesh_cube : :class:`iris.cube.Cube` An unstructured instance of :class:`~iris.cube.Cube` that supplies the desired horizontal mesh definition. mdtol : float, default=0 @@ -410,9 +410,6 @@ def regrid_unstructured_to_unstructured( :attr:`~esmpy.api.constants.RegridMethod.CONSERVE` or :attr:`~esmpy.api.constants.RegridMethod.BILINEAR` or :attr:`~esmpy.api.constants.RegridMethod.NEAREST` used to calculate weights. - src_resolution : int, optional - If present, represents the amount of latitude slices per cell - given to ESMF for calculation. use_src_mask : :obj:`~numpy.typing.ArrayLike` or bool, default=False Either an array representing the cells in the source to ignore, or else a boolean value. If True, this array is taken from the mask on the data diff --git a/esmf_regrid/schemes.py b/esmf_regrid/schemes.py index a1cdc81b..59e723d2 100644 --- a/esmf_regrid/schemes.py +++ b/esmf_regrid/schemes.py @@ -516,6 +516,13 @@ def _regrid_rectilinear_to_rectilinear__prepare( src_mask=None, tgt_mask=None, ): + """ + First (setup) part of 'regrid_rectilinear_to_rectilinear'. + + Check inputs and calculate the sparse regrid matrix and related info. + The 'regrid info' returned can be re-used over many 2d slices. + + """ tgt_x = _get_coord(tgt_grid_cube, "x") tgt_y = _get_coord(tgt_grid_cube, "y") src_x = _get_coord(src_grid_cube, "x") @@ -544,6 +551,12 @@ def _regrid_rectilinear_to_rectilinear__prepare( def _regrid_rectilinear_to_rectilinear__perform(src_cube, regrid_info, mdtol): + """ + Second (regrid) part of 'regrid_rectilinear_to_rectilinear'. + + Perform the prepared regrid calculation on a single cube. + + """ grid_x_dim, grid_y_dim = regrid_info.dims grid_x, grid_y = regrid_info.target regridder = regrid_info.regridder @@ -778,6 +791,13 @@ def _regrid_unstructured_to_unstructured__prepare( src_location=None, tgt_location=None, ): + """ + First (setup) part of 'regrid_unstructured_to_unstructured'. + + Check inputs and calculate the sparse regrid matrix and related info. + The 'regrid info' returned can be re-used over many 2d slices. + + """ if isinstance(tgt_cube_or_mesh, Mesh): mesh = tgt_cube_or_mesh location = tgt_location @@ -811,6 +831,12 @@ def _regrid_unstructured_to_unstructured__prepare( def _regrid_unstructured_to_unstructured__perform(src_cube, regrid_info, mdtol): + """ + Second (regrid) part of 'regrid_unstructured_to_unstructured'. + + Perform the prepared regrid calculation on a single cube. + + """ (mesh_dim,) = regrid_info.dims mesh, location = regrid_info.target regridder = regrid_info.regridder From f20a62a0870610fd992f12ba2f7d978aba621ad5 Mon Sep 17 00:00:00 2001 From: Henry Wright Date: Thu, 2 Nov 2023 16:22:13 +0000 Subject: [PATCH 15/15] more docstring changes --- .../experimental/unstructured_scheme.py | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/esmf_regrid/experimental/unstructured_scheme.py b/esmf_regrid/experimental/unstructured_scheme.py index e6562ac0..ccda7214 100644 --- a/esmf_regrid/experimental/unstructured_scheme.py +++ b/esmf_regrid/experimental/unstructured_scheme.py @@ -370,23 +370,9 @@ def regrid_unstructured_to_unstructured( Return a new :class:`~iris.cube.Cube` with :attr:`~iris.cube.Cube.data` values calculated using weights generated by :mod:`esmpy` to give the weighted - mean of :attr:`~iris.cube.Cube.data` values from ``src_cube`` regridded onto the - horizontal mesh of ``mesh_cube``. The dimensions on the :class:`~iris.cube.Cube` associated - with the grid will be replaced by a dimension associated with the - :attr:`~iris.cube.Cube.mesh`. - That dimension will be the first of the grid dimensions, whether - it is associated with the ``x`` or ``y`` coordinate. Since two dimensions are - being replaced by one, coordinates associated with dimensions after - the grid will become associated with dimensions one lower. - This function requires that the horizontal dimension of ``mesh_cube`` is - described by a 2D mesh with data located on the faces of that mesh - for conservative regridding and located on either faces or nodes for - bilinear regridding. - This function allows the horizontal grid of ``grid_cube`` to be either - rectilinear or curvilinear (i.e. expressed in terms of two orthogonal - 1D coordinates or via a pair of 2D coordinates). - This function also requires that the :class:`~iris.coords.Coord`\\ s describing the - horizontal grid have :attr:`~iris.coords.Coord.bounds`. + mean of :attr:`~iris.cube.Cube.data` values from ``src_mesh_cube`` regridded onto the + horizontal mesh of ``tgt_mesh_cube``. The resulting cube will have the same + ``mesh_dim`` as ``src_mesh_cube``. Parameters ----------