コード例 #1
0
def calculate_divg_del6(
    sin_sg,
    sina_u,
    sina_v,
    dx,
    dy,
    dxc,
    dyc,
    nhalo: int,
    tile_partitioner: TilePartitioner,
    rank: int,
):

    divg_u = sina_v * dyc / dx
    del6_u = sina_v * dx / dyc
    divg_v = sina_u * dxc / dy
    del6_v = sina_u * dy / dxc

    if tile_partitioner.on_tile_bottom(rank):
        divg_u[:, nhalo] = (0.5 *
                            (sin_sg[:, nhalo, 1] + sin_sg[:, nhalo - 1, 3]) *
                            dyc[:, nhalo] / dx[:, nhalo])
        del6_u[:, nhalo] = (0.5 *
                            (sin_sg[:, nhalo, 1] + sin_sg[:, nhalo - 1, 3]) *
                            dx[:, nhalo] / dyc[:, nhalo])
    if tile_partitioner.on_tile_top(rank):
        divg_u[:, -nhalo -
               1] = (0.5 * (sin_sg[:, -nhalo, 1] + sin_sg[:, -nhalo - 1, 3]) *
                     dyc[:, -nhalo - 1] / dx[:, -nhalo - 1])
        del6_u[:, -nhalo -
               1] = (0.5 * (sin_sg[:, -nhalo, 1] + sin_sg[:, -nhalo - 1, 3]) *
                     dx[:, -nhalo - 1] / dyc[:, -nhalo - 1])
    if tile_partitioner.on_tile_left(rank):
        divg_v[nhalo, :] = (0.5 *
                            (sin_sg[nhalo, :, 0] + sin_sg[nhalo - 1, :, 2]) *
                            dxc[nhalo, :] / dy[nhalo, :])
        del6_v[nhalo, :] = (0.5 *
                            (sin_sg[nhalo, :, 0] + sin_sg[nhalo - 1, :, 2]) *
                            dy[nhalo, :] / dxc[nhalo, :])
    if tile_partitioner.on_tile_right(rank):
        divg_v[-nhalo -
               1, :] = (0.5 *
                        (sin_sg[-nhalo, :, 0] + sin_sg[-nhalo - 1, :, 2]) *
                        dxc[-nhalo - 1, :] / dy[-nhalo - 1, :])
        del6_v[-nhalo -
               1, :] = (0.5 *
                        (sin_sg[-nhalo, :, 0] + sin_sg[-nhalo - 1, :, 2]) *
                        dy[-nhalo - 1, :] / dxc[-nhalo - 1, :])

    return divg_u, divg_v, del6_u, del6_v
コード例 #2
0
def calc_unit_vector_west(
    xyz_dgrid,
    xyz_agrid,
    grid_type: int,
    nhalo: int,
    tile_partitioner: TilePartitioner,
    rank: int,
    np,
):
    """
    Calculates the cartesian unit vectors at the left/right edges of each grid cell.

    Returns:
        vector1: the horizontal unit vector
        vector2: the vertical unit vector

    """
    ew1 = np.zeros((xyz_dgrid.shape[0], xyz_agrid.shape[1], 3))
    ew2 = np.zeros((xyz_dgrid.shape[0], xyz_agrid.shape[1], 3))
    if grid_type < 3:

        pp = xyz_midpoint(xyz_dgrid[1:-1, :-1, :3], xyz_dgrid[1:-1, 1:, :3])

        p2 = np.cross(xyz_agrid[:-1, :, :3], xyz_agrid[1:, :, :3])
        if tile_partitioner.on_tile_left(rank):
            p2[nhalo - 1] = np.cross(pp[nhalo - 1], xyz_agrid[nhalo, :, :3])
        if tile_partitioner.on_tile_right(rank):
            p2[-nhalo] = np.cross(xyz_agrid[-nhalo - 1, :, :3], pp[-nhalo])

        ew1[1:-1, :, :] = normalize_xyz(np.cross(p2, pp))
        p1 = np.cross(xyz_dgrid[1:-1, :-1, :], xyz_dgrid[1:-1, 1:, :])
        ew2[1:-1, :, :] = normalize_xyz(np.cross(p1, pp))

        # fill ghost on ew:
        _fill_halo_corners(ew1, 0.0, nhalo, tile_partitioner, rank)
        _fill_halo_corners(ew2, 0.0, nhalo, tile_partitioner, rank)

    else:
        ew1[:, :, 1] = 1.0
        ew2[:, :, 2] = 1.0

    return ew1[1:-1, :, :], ew2[1:-1, :, :]
コード例 #3
0
def calc_unit_vector_south(
    xyz_dgrid,
    xyz_agrid,
    grid_type: int,
    nhalo: int,
    tile_partitioner: TilePartitioner,
    rank: int,
    np,
):
    """
    Calculates the cartesian unit vectors at the top/bottom edges of each grid cell.

    Returns:
        vector1: the horizontal unit vector
        vector2: the vertical unit vector
    """
    es1 = np.zeros((xyz_agrid.shape[0], xyz_dgrid.shape[1], 3))
    es2 = np.zeros((xyz_agrid.shape[0], xyz_dgrid.shape[1], 3))
    if grid_type < 3:

        pp = xyz_midpoint(xyz_dgrid[:-1, 1:-1, :3], xyz_dgrid[1:, 1:-1, :3])
        p2 = np.cross(xyz_agrid[:, :-1, :3], xyz_agrid[:, 1:, :3])
        if tile_partitioner.on_tile_bottom(rank):
            p2[:, nhalo - 1] = np.cross(pp[:, nhalo - 1], xyz_agrid[:,
                                                                    nhalo, :3])
        if tile_partitioner.on_tile_top(rank):
            p2[:, -nhalo] = np.cross(xyz_agrid[:, -nhalo - 1, :3], pp[:,
                                                                      -nhalo])

        es2[:, 1:-1, :] = normalize_xyz(np.cross(p2, pp))

        p1 = np.cross(xyz_dgrid[:-1, 1:-1, :], xyz_dgrid[1:, 1:-1, :])
        es1[:, 1:-1, :] = normalize_xyz(np.cross(p1, pp))

        # fill ghost on es:
        _fill_halo_corners(es1, 0.0, nhalo, tile_partitioner, rank)
        _fill_halo_corners(es2, 0.0, nhalo, tile_partitioner, rank)
    else:
        es1[:, :, 1] = 1.0
        es2[:, :, 2] = 1.0

    return es1[:, 1:-1, :], es2[:, 1:-1, :]
コード例 #4
0
def calculate_xy_unit_vectors(xyz_dgrid, nhalo: int,
                              tile_partitioner: TilePartitioner, rank: int,
                              np):
    """
    Calculates the cartesian unit vectors at the corners of each grid cell.
    vector1 is the horizontal unit vector, while
    vector2 is the vertical unit vector
    """
    cross_vect_x = np.cross(
        xyz_dgrid[nhalo - 1:-nhalo - 1, nhalo:-nhalo, :],
        xyz_dgrid[nhalo + 1:-nhalo + 1, nhalo:-nhalo, :],
    )
    if tile_partitioner.on_tile_left(rank):
        cross_vect_x[0, :] = np.cross(xyz_dgrid[nhalo, nhalo:-nhalo, :],
                                      xyz_dgrid[nhalo + 1, nhalo:-nhalo, :])
    if tile_partitioner.on_tile_right(rank):
        cross_vect_x[-1, :] = np.cross(
            xyz_dgrid[-nhalo - 2, nhalo:-nhalo, :],
            xyz_dgrid[-nhalo - 1, nhalo:-nhalo, :],
        )
    unit_x_vector = normalize_xyz(
        np.cross(cross_vect_x, xyz_dgrid[nhalo:-nhalo, nhalo:-nhalo]))

    cross_vect_y = np.cross(
        xyz_dgrid[nhalo:-nhalo, nhalo - 1:-nhalo - 1, :],
        xyz_dgrid[nhalo:-nhalo, nhalo + 1:-nhalo + 1, :],
    )
    if tile_partitioner.on_tile_bottom(rank):
        cross_vect_y[:, 0] = np.cross(xyz_dgrid[nhalo:-nhalo, nhalo, :],
                                      xyz_dgrid[nhalo:-nhalo, nhalo + 1, :])
    if tile_partitioner.on_tile_top(rank):
        cross_vect_y[:, -1] = np.cross(
            xyz_dgrid[nhalo:-nhalo, -nhalo - 2, :],
            xyz_dgrid[nhalo:-nhalo, -nhalo - 1, :],
        )
    unit_y_vector = normalize_xyz(
        np.cross(cross_vect_y, xyz_dgrid[nhalo:-nhalo, nhalo:-nhalo]))

    return unit_x_vector, unit_y_vector
コード例 #5
0
def supergrid_corner_fix(cos_sg, sin_sg, nhalo: int,
                         tile_partitioner: TilePartitioner, rank: int):
    """
    filling the ghost cells overwrites some of the sin_sg
    values along the outward-facing edge of a tile in the corners, which is incorrect.
    This function resolves the issue by filling in the appropriate values
    after the _fill_single_halo_corner call
    """
    big_number = 1.0e8
    tiny_number = 1.0e-8

    if tile_partitioner.on_tile_left(rank):
        if tile_partitioner.on_tile_bottom(rank):
            _fill_single_halo_corner(sin_sg, tiny_number, nhalo, "sw")
            _fill_single_halo_corner(cos_sg, big_number, nhalo, "sw")
            _rotate_trig_sg_sw_counterclockwise(sin_sg[:, :, 1],
                                                sin_sg[:, :, 2], nhalo)
            _rotate_trig_sg_sw_counterclockwise(cos_sg[:, :, 1],
                                                cos_sg[:, :, 2], nhalo)
            _rotate_trig_sg_sw_clockwise(sin_sg[:, :, 0], sin_sg[:, :, 3],
                                         nhalo)
            _rotate_trig_sg_sw_clockwise(cos_sg[:, :, 0], cos_sg[:, :, 3],
                                         nhalo)
        if tile_partitioner.on_tile_top(rank):
            _fill_single_halo_corner(sin_sg, tiny_number, nhalo, "nw")
            _fill_single_halo_corner(cos_sg, big_number, nhalo, "nw")
            _rotate_trig_sg_nw_counterclockwise(sin_sg[:, :, 0],
                                                sin_sg[:, :, 1], nhalo)
            _rotate_trig_sg_nw_counterclockwise(cos_sg[:, :, 0],
                                                cos_sg[:, :, 1], nhalo)
            _rotate_trig_sg_nw_clockwise(sin_sg[:, :, 3], sin_sg[:, :, 2],
                                         nhalo)
            _rotate_trig_sg_nw_clockwise(cos_sg[:, :, 3], cos_sg[:, :, 2],
                                         nhalo)
    if tile_partitioner.on_tile_right(rank):
        if tile_partitioner.on_tile_bottom(rank):
            _fill_single_halo_corner(sin_sg, tiny_number, nhalo, "se")
            _fill_single_halo_corner(cos_sg, big_number, nhalo, "se")
            _rotate_trig_sg_se_clockwise(sin_sg[:, :, 1], sin_sg[:, :, 0],
                                         nhalo)
            _rotate_trig_sg_se_clockwise(cos_sg[:, :, 1], cos_sg[:, :, 0],
                                         nhalo)
            _rotate_trig_sg_se_counterclockwise(sin_sg[:, :, 2],
                                                sin_sg[:, :, 3], nhalo)
            _rotate_trig_sg_se_counterclockwise(cos_sg[:, :, 2],
                                                cos_sg[:, :, 3], nhalo)
        if tile_partitioner.on_tile_top(rank):
            _fill_single_halo_corner(sin_sg, tiny_number, nhalo, "ne")
            _fill_single_halo_corner(cos_sg, big_number, nhalo, "ne")
            _rotate_trig_sg_ne_counterclockwise(sin_sg[:, :, 3],
                                                sin_sg[:, :, 0], nhalo)
            _rotate_trig_sg_ne_counterclockwise(cos_sg[:, :, 3],
                                                cos_sg[:, :, 0], nhalo)
            _rotate_trig_sg_ne_clockwise(sin_sg[:, :, 2], sin_sg[:, :, 1],
                                         nhalo)
            _rotate_trig_sg_ne_clockwise(cos_sg[:, :, 2], cos_sg[:, :, 1],
                                         nhalo)
コード例 #6
0
def edge_factors(
    grid_quantity: Quantity,
    agrid,
    grid_type: int,
    nhalo: int,
    tile_partitioner: TilePartitioner,
    rank: int,
    radius: float,
    np,
):
    """
    Creates interpolation factors from the A grid to the B grid on tile edges
    """
    grid = grid_quantity.data[:]
    big_number = 1.0e8
    i_range = grid[nhalo:-nhalo, nhalo:-nhalo].shape[0]
    j_range = grid[nhalo:-nhalo, nhalo:-nhalo].shape[1]
    edge_n = np.zeros(i_range) + big_number
    edge_s = np.zeros(i_range) + big_number
    edge_e = np.zeros(j_range) + big_number
    edge_w = np.zeros(j_range) + big_number
    npx, npy, ndims = tile_partitioner.global_extent(grid_quantity)
    slice_x, slice_y = tile_partitioner.subtile_slice(rank, grid_quantity.dims,
                                                      (npx, npy))
    global_is = nhalo + slice_x.start
    global_js = nhalo + slice_y.start
    global_ie = nhalo + slice_x.stop - 1
    global_je = nhalo + slice_y.stop - 1
    jstart = max(4, global_js) - global_js + nhalo
    jend = min(npy + nhalo - 1, global_je + 2) - global_js + nhalo
    istart = max(4, global_is) - global_is + nhalo
    iend = min(npx + nhalo - 1, global_ie + 2) - global_is + nhalo
    if grid_type < 3:
        if tile_partitioner.on_tile_left(rank):
            edge_w[jstart - nhalo:jend - nhalo] = set_west_edge_factor(
                grid, agrid, nhalo, radius, jstart, jend, np)
        if tile_partitioner.on_tile_right(rank):
            edge_e[jstart - nhalo:jend - nhalo] = set_east_edge_factor(
                grid, agrid, nhalo, radius, jstart, jend, np)
        if tile_partitioner.on_tile_bottom(rank):
            edge_s[istart - nhalo:iend - nhalo] = set_south_edge_factor(
                grid, agrid, nhalo, radius, istart, iend, np)
        if tile_partitioner.on_tile_top(rank):
            edge_n[istart - nhalo:iend - nhalo] = set_north_edge_factor(
                grid, agrid, nhalo, radius, istart, iend, np)

    return edge_w, edge_e, edge_s, edge_n
コード例 #7
0
def efactor_a2c_v(
    grid_quantity: Quantity,
    agrid,
    grid_type: int,
    nhalo: int,
    tile_partitioner: TilePartitioner,
    rank: int,
    radius: float,
    np,
):
    """
    Creates interpolation factors at tile edges
    for interpolating vectors from A to C grids
    """
    big_number = 1.0e8
    grid = grid_quantity.data[:]
    npx, npy, ndims = tile_partitioner.global_extent(grid_quantity)
    slice_x, slice_y = tile_partitioner.subtile_slice(rank, grid_quantity.dims,
                                                      (npx, npy))
    global_is = nhalo + slice_x.start
    global_js = nhalo + slice_y.start

    if npx != npy:
        raise ValueError("npx must equal npy")
    if npx % 2 == 0:
        raise ValueError("npx must be odd")
    i_midpoint = int((npx - 1) / 2)
    j_midpoint = int((npy - 1) / 2)
    i_indices = np.arange(agrid.shape[0] - nhalo + 1) + global_is - nhalo
    j_indices = np.arange(agrid.shape[1] - nhalo + 1) + global_js - nhalo
    i_selection = i_indices[i_indices <= nhalo + i_midpoint]
    j_selection = j_indices[j_indices <= nhalo + j_midpoint]
    if len(i_selection) > 0:
        im2 = max(i_selection) - global_is
    else:
        im2 = len(i_selection)
    if len(i_selection) == len(i_indices):
        im2 = len(i_selection) - nhalo
    if len(j_selection) > 0:
        jm2 = max(j_selection) - global_js
    else:
        jm2 = len(j_selection)
    if len(j_selection) == len(j_indices):
        jm2 = len(j_selection) - nhalo
    im2 = max(im2, -1)
    jm2 = max(jm2, -1)

    edge_vect_s = np.zeros(grid.shape[0] - 1) + big_number
    edge_vect_n = np.zeros(grid.shape[0] - 1) + big_number
    edge_vect_e = np.zeros(grid.shape[1] - 1) + big_number
    edge_vect_w = np.zeros(grid.shape[1] - 1) + big_number
    if grid_type < 3:
        if tile_partitioner.on_tile_left(rank):
            edge_vect_w[2:-2] = calculate_west_edge_vectors(
                grid, agrid, jm2, nhalo, radius, np)
            if tile_partitioner.on_tile_bottom(rank):
                edge_vect_w[nhalo - 1] = edge_vect_w[nhalo]
            if tile_partitioner.on_tile_top(rank):
                edge_vect_w[-nhalo] = edge_vect_w[-nhalo - 1]
        if tile_partitioner.on_tile_right(rank):
            edge_vect_e[2:-2] = calculate_east_edge_vectors(
                grid, agrid, jm2, nhalo, radius, np)
            if tile_partitioner.on_tile_bottom(rank):
                edge_vect_e[nhalo - 1] = edge_vect_e[nhalo]
            if tile_partitioner.on_tile_top(rank):
                edge_vect_e[-nhalo] = edge_vect_e[-nhalo - 1]
        if tile_partitioner.on_tile_bottom(rank):
            edge_vect_s[2:-2] = calculate_south_edge_vectors(
                grid, agrid, im2, nhalo, radius, np)
            if tile_partitioner.on_tile_left(rank):
                edge_vect_s[nhalo - 1] = edge_vect_s[nhalo]
            if tile_partitioner.on_tile_right(rank):
                edge_vect_s[-nhalo] = edge_vect_s[-nhalo - 1]
        if tile_partitioner.on_tile_top(rank):
            edge_vect_n[2:-2] = calculate_north_edge_vectors(
                grid, agrid, im2, nhalo, radius, np)
            if tile_partitioner.on_tile_left(rank):
                edge_vect_n[nhalo - 1] = edge_vect_n[nhalo]
            if tile_partitioner.on_tile_right(rank):
                edge_vect_n[-nhalo] = edge_vect_n[-nhalo - 1]

    return edge_vect_w, edge_vect_e, edge_vect_s, edge_vect_n
コード例 #8
0
def calculate_trig_uv(
    xyz_dgrid,
    cos_sg,
    sin_sg,
    nhalo: int,
    tile_partitioner: TilePartitioner,
    rank: int,
    np,
):
    """
    Calculates more trig quantities
    """

    big_number = 1.0e8
    tiny_number = 1.0e-8

    dgrid_shape_2d = xyz_dgrid[:, :, 0].shape
    cosa = np.zeros(dgrid_shape_2d) + big_number
    sina = np.zeros(dgrid_shape_2d) + big_number
    cosa_u = np.zeros((dgrid_shape_2d[0], dgrid_shape_2d[1] - 1)) + big_number
    sina_u = np.zeros((dgrid_shape_2d[0], dgrid_shape_2d[1] - 1)) + big_number
    rsin_u = np.zeros((dgrid_shape_2d[0], dgrid_shape_2d[1] - 1)) + big_number
    cosa_v = np.zeros((dgrid_shape_2d[0] - 1, dgrid_shape_2d[1])) + big_number
    sina_v = np.zeros((dgrid_shape_2d[0] - 1, dgrid_shape_2d[1])) + big_number
    rsin_v = np.zeros((dgrid_shape_2d[0] - 1, dgrid_shape_2d[1])) + big_number

    cosa[nhalo:-nhalo,
         nhalo:-nhalo] = 0.5 * (cos_sg[nhalo - 1:-nhalo, nhalo - 1:-nhalo, 7] +
                                cos_sg[nhalo:-nhalo + 1, nhalo:-nhalo + 1, 5])
    sina[nhalo:-nhalo,
         nhalo:-nhalo] = 0.5 * (sin_sg[nhalo - 1:-nhalo, nhalo - 1:-nhalo, 7] +
                                sin_sg[nhalo:-nhalo + 1, nhalo:-nhalo + 1, 5])

    cosa_u[1:-1, :] = 0.5 * (cos_sg[:-1, :, 2] + cos_sg[1:, :, 0])
    sina_u[1:-1, :] = 0.5 * (sin_sg[:-1, :, 2] + sin_sg[1:, :, 0])
    sinu2 = sina_u[1:-1, :]**2
    sinu2[sinu2 < tiny_number] = tiny_number
    rsin_u[1:-1, :] = 1.0 / sinu2

    cosa_v[:, 1:-1] = 0.5 * (cos_sg[:, :-1, 3] + cos_sg[:, 1:, 1])
    sina_v[:, 1:-1] = 0.5 * (sin_sg[:, :-1, 3] + sin_sg[:, 1:, 1])
    sinv2 = sina_v[:, 1:-1]**2
    sinv2[sinv2 < tiny_number] = tiny_number
    rsin_v[:, 1:-1] = 1.0 / sinv2

    cosa_s = cos_sg[:, :, 4]
    sin2 = sin_sg[:, :, 4]**2
    sin2[sin2 < tiny_number] = tiny_number
    rsin2 = 1.0 / sin2

    # fill ghost on cosa_s:
    _fill_halo_corners(cosa_s, big_number, nhalo, tile_partitioner, rank)

    sina2 = sina[nhalo:-nhalo, nhalo:-nhalo]**2
    sina2[sina2 < tiny_number] = tiny_number
    rsina = 1.0 / sina2

    # Set special sin values at edges
    if tile_partitioner.on_tile_left(rank):
        rsina[0, :] = big_number
        sina_u_limit = sina_u[nhalo, :]
        sina_u_limit[abs(sina_u_limit) < tiny_number] = tiny_number * np.sign(
            sina_u_limit[abs(sina_u_limit) < tiny_number])
        rsin_u[nhalo, :] = 1.0 / sina_u_limit
    if tile_partitioner.on_tile_right(rank):
        rsina[-1, :] = big_number
        sina_u_limit = sina_u[-nhalo - 1, :]
        sina_u_limit[abs(sina_u_limit) < tiny_number] = tiny_number * np.sign(
            sina_u_limit[abs(sina_u_limit) < tiny_number])
        rsin_u[-nhalo - 1, :] = 1.0 / sina_u_limit
    if tile_partitioner.on_tile_bottom(rank):
        rsina[:, 0] = big_number
        sina_v_limit = sina_v[:, nhalo]
        sina_v_limit[abs(sina_v_limit) < tiny_number] = tiny_number * np.sign(
            sina_v_limit[abs(sina_v_limit) < tiny_number])
        rsin_v[:, nhalo] = 1.0 / sina_v_limit
    if tile_partitioner.on_tile_top(rank):
        rsina[:, -1] = big_number
        sina_v_limit = sina_v[:, -nhalo - 1]
        sina_v_limit[abs(sina_v_limit) < tiny_number] = tiny_number * np.sign(
            sina_v_limit[abs(sina_v_limit) < tiny_number])
        rsin_v[:, -nhalo - 1] = 1.0 / sina_v_limit

    return (
        cosa,
        sina,
        cosa_u,
        cosa_v,
        cosa_s,
        sina_u,
        sina_v,
        rsin_u,
        rsin_v,
        rsina,
        rsin2,
    )
コード例 #9
0
def calculate_supergrid_cos_sin(
    xyz_dgrid,
    xyz_agrid,
    ec1,
    ec2,
    grid_type: int,
    nhalo: int,
    tile_partitioner: TilePartitioner,
    rank: int,
    np,
):
    """
    Calculates the cosine and sine of the grid angles at each of the following points
    in a supergrid cell:
    9---4---8
    |       |
    1   5   3
    |       |
    6---2---7
    """
    big_number = 1.0e8
    tiny_number = 1.0e-8

    shape_a = xyz_agrid.shape
    cos_sg = np.zeros((shape_a[0], shape_a[1], 9)) + big_number
    sin_sg = np.zeros((shape_a[0], shape_a[1], 9)) + tiny_number

    if grid_type < 3:
        cos_sg[:, :, 5] = spherical_cos(xyz_dgrid[:-1, :-1, :],
                                        xyz_dgrid[1:, :-1, :],
                                        xyz_dgrid[:-1, 1:, :], np)
        cos_sg[:, :, 6] = -1 * spherical_cos(xyz_dgrid[1:, :-1, :],
                                             xyz_dgrid[:-1, :-1, :],
                                             xyz_dgrid[1:, 1:, :], np)
        cos_sg[:, :,
               7] = spherical_cos(xyz_dgrid[1:, 1:, :], xyz_dgrid[1:, :-1, :],
                                  xyz_dgrid[:-1, 1:, :], np)
        cos_sg[:, :, 8] = -1 * spherical_cos(
            xyz_dgrid[:-1,
                      1:, :], xyz_dgrid[:-1, :-1, :], xyz_dgrid[1:, 1:, :], np)

        midpoint = xyz_midpoint(xyz_dgrid[:-1, :-1, :], xyz_dgrid[:-1, 1:, :])
        cos_sg[:, :, 0] = spherical_cos(midpoint, xyz_agrid[:, :, :],
                                        xyz_dgrid[:-1, 1:, :], np)
        midpoint = xyz_midpoint(xyz_dgrid[:-1, :-1, :], xyz_dgrid[1:, :-1, :])
        cos_sg[:, :, 1] = spherical_cos(midpoint, xyz_dgrid[1:, :-1, :],
                                        xyz_agrid[:, :, :], np)
        midpoint = xyz_midpoint(xyz_dgrid[1:, :-1, :], xyz_dgrid[1:, 1:, :])
        cos_sg[:, :, 2] = spherical_cos(midpoint, xyz_agrid[:, :, :],
                                        xyz_dgrid[1:, :-1, :], np)
        midpoint = xyz_midpoint(xyz_dgrid[:-1, 1:, :], xyz_dgrid[1:, 1:, :])
        cos_sg[:, :, 3] = spherical_cos(midpoint, xyz_dgrid[:-1, 1:, :],
                                        xyz_agrid[:, :, :], np)

        cos_sg[:, :, 4] = np.sum(ec1 * ec2, axis=-1)

        cos_sg[abs(1.0 - cos_sg) < 1e-15] = 1.0

        sin_sg_tmp = 1.0 - cos_sg**2
        sin_sg_tmp[sin_sg_tmp < 0] = 0.0
        sin_sg = np.sqrt(sin_sg_tmp)
        sin_sg[sin_sg > 1.0] = 1.0

        # Adjust for corners:
        if tile_partitioner.on_tile_left(rank):
            if tile_partitioner.on_tile_bottom(rank):  # southwest corner
                sin_sg[nhalo - 1, :nhalo, 2] = sin_sg[:nhalo, nhalo, 1]
                sin_sg[:nhalo, nhalo - 1, 3] = sin_sg[nhalo, :nhalo, 0]
            if tile_partitioner.on_tile_top(rank):  # northwest corner
                sin_sg[nhalo - 1, -nhalo:, 2] = sin_sg[:nhalo, -nhalo - 1,
                                                       3][::-1]
                sin_sg[:nhalo, -nhalo, 1] = sin_sg[nhalo,
                                                   -nhalo - 2:-nhalo + 1, 0]
        if tile_partitioner.on_tile_right(rank):
            if tile_partitioner.on_tile_bottom(rank):  # southeast corner
                sin_sg[-nhalo, :nhalo, 0] = sin_sg[-nhalo:, nhalo, 1][::-1]
                sin_sg[-nhalo:, nhalo - 1, 3] = sin_sg[-nhalo - 1, :nhalo,
                                                       2][::-1]
            if tile_partitioner.on_tile_top(rank):  # northeast corner
                sin_sg[-nhalo, -nhalo:, 0] = sin_sg[-nhalo:, -nhalo - 1, 3]
                sin_sg[-nhalo:, -nhalo, 1] = sin_sg[-nhalo - 1, -nhalo:, 2]

    else:
        cos_sg[:] = 0.0
        sin_sg[:] = 1.0

    return cos_sg, sin_sg