def test_global_grid(): """Test conversion of a global grid.""" n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) cube = _grid_cube( n_lons, n_lats, lon_bounds, lat_bounds, circular=True, coord_system=GeogCS(EARTH_RADIUS), ) gridinfo = _cube_to_GridInfo(cube) # Ensure conversion to ESMF works without error _ = gridinfo.make_esmf_field() # The following test ensures there are no overlapping cells. # This catches geometric/topological abnormalities that would arise from, # for example: switching lat/lon values, using euclidean coords vs spherical. rg = Regridder(gridinfo, gridinfo) expected_weights = scipy.sparse.identity(n_lats * n_lons) assert np.array_equal(expected_weights.todense(), rg.weight_matrix.todense()) assert gridinfo.crs == GeogCS(EARTH_RADIUS).as_cartopy_crs()
def _regrid_rectilinear_to_unstructured__prepare( src_grid_cube, target_mesh_cube, method, precomputed_weights=None, resolution=None, ): """ First (setup) part of 'regrid_rectilinear_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. """ grid_x = src_grid_cube.coord(axis="x") grid_y = src_grid_cube.coord(axis="y") mesh = target_mesh_cube.mesh location = target_mesh_cube.location if mesh is None: raise ValueError("The given cube is not defined on a mesh.") if method == "conservative": if location != "face": raise ValueError( f"Conservative regridding requires a target cube located on " f"the face of a cube, target cube had the {location} location." ) center = False elif method == "bilinear": if location not in ["face", "node"]: raise ValueError( f"Bilinear regridding requires a target cube with a node " f"or face location, target cube had the {location} location." ) if location == "face" and None in mesh.face_coords: raise ValueError( "Bilinear regridding requires a target cube on a face location to have " "a face center." ) center = True else: raise ValueError( f"method must be either 'bilinear' or 'conservative', got '{method}'." ) assert mesh is not None if grid_x.ndim == 1: (grid_x_dim,) = src_grid_cube.coord_dims(grid_x) (grid_y_dim,) = src_grid_cube.coord_dims(grid_y) else: grid_y_dim, grid_x_dim = src_grid_cube.coord_dims(grid_x) meshinfo = _mesh_to_MeshInfo(mesh, location) gridinfo = _cube_to_GridInfo(src_grid_cube, center=center, resolution=resolution) regridder = Regridder( gridinfo, meshinfo, method=method, precomputed_weights=precomputed_weights ) regrid_info = (grid_x_dim, grid_y_dim, grid_x, grid_y, mesh, location, regridder) return regrid_info
def test_curvilinear_grid(): """Test conversion of a curvilinear global grid.""" n_lons = 6 n_lats = 5 lon_bounds = (-180, 180) lat_bounds = (-90, 90) cube = _curvilinear_cube( n_lons, n_lats, lon_bounds, lat_bounds, coord_system=GeogCS(EARTH_RADIUS), ) gridinfo = _cube_to_GridInfo(cube) # Ensure conversion to ESMF works without error _ = gridinfo.make_esmf_field() # The following test ensures there are no overlapping cells. # This catches geometric/topological abnormalities that would arise from, # for example: switching lat/lon values, using euclidean coords vs spherical. rg = Regridder(gridinfo, gridinfo) expected_weights = scipy.sparse.identity(n_lats * n_lons) assert np.array_equal(expected_weights.todense(), rg.weight_matrix.todense()) assert gridinfo.crs == GeogCS(EARTH_RADIUS).as_cartopy_crs() # While curvilinear coords do not have the "circular" attribute, the code # allows "circular" to be True when setting the core regridder directly. # This describes an ESMF object which is topologically different, but ought # to be geometrically equivalent to the non-circular case. circular_gridinfo = _cube_to_GridInfo(cube) circular_gridinfo.circular = True rg_circular = Regridder(circular_gridinfo, gridinfo) assert np.allclose(expected_weights.todense(), rg_circular.weight_matrix.todense())
def test_local_grid(): """Test conversion of a local grid.""" n_lons = 6 n_lats = 5 lon_bounds = (-20, 20) lat_bounds = (20, 60) cube = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds) gridinfo = _cube_to_GridInfo(cube) # Ensure conversion to ESMF works without error _ = gridinfo.make_esmf_field() # The following test ensures there are no overlapping cells. # Note that this test fails when longitude is circular. rg = Regridder(gridinfo, gridinfo) expected_weights = scipy.sparse.identity(n_lats * n_lons) assert np.array_equal(expected_weights.todense(), rg.weight_matrix.todense())
def test_grid_with_scalars(): """Test conversion of a grid with scalar coords.""" n_lons = 1 n_lats = 5 lon_bounds = (-20, 20) lat_bounds = (20, 60) cube = _grid_cube(n_lons, n_lats, lon_bounds, lat_bounds) # Convert longitude to a scalar cube = cube[:, 0] assert len(cube.shape) == 1 gridinfo = _cube_to_GridInfo(cube) # Ensure conversion to ESMF works without error _ = gridinfo.make_esmf_field() # The following test ensures there are no overlapping cells. rg = Regridder(gridinfo, gridinfo) expected_weights = scipy.sparse.identity(n_lats * n_lons) assert np.array_equal(expected_weights.todense(), rg.weight_matrix.todense())