Пример #1
0
    def test_connectivity_start_index(self):
        """Test a mesh where some connectivities have start_index = 1."""
        # Make a mesh with both faces *and* some edges
        mesh = make_mesh(n_edges=7)
        # Get the face-node and edge-node connectivities
        face_nodes_conn = mesh.face_node_connectivity
        edge_nodes_conn = mesh.edge_node_connectivity
        edge_nodes_conn2 = Connectivity(
            indices=edge_nodes_conn.indices + 1,
            cf_role=edge_nodes_conn.cf_role,
            var_name="edges_x_2",
            start_index=1,
        )
        # Make a new mesh with altered connectivities.
        mesh2 = Mesh(
            topology_dimension=mesh.topology_dimension,
            node_coords_and_axes=zip(mesh.node_coords, XY_LOCS),
            face_coords_and_axes=zip(mesh.face_coords, XY_LOCS),
            connectivities=[face_nodes_conn, edge_nodes_conn2],
        )

        # Save and snapshot the result
        tempfile_path = self.check_save_mesh(mesh2)
        dims, vars = scan_dataset(tempfile_path)

        # Check shape and dimensions of the associated connectivity variables.
        (mesh_name,) = vars_meshnames(vars)
        mesh_props = vars[mesh_name]
        faceconn_name = mesh_props["face_node_connectivity"]
        edgeconn_name = mesh_props["edge_node_connectivity"]
        faceconn_props = vars[faceconn_name]
        edgeconn_props = vars[edgeconn_name]
        self.assertEqual(faceconn_props["start_index"], 0)
        self.assertEqual(edgeconn_props["start_index"], 1)
Пример #2
0
 def test_2d_coord(self):
     cube = simple_2d_w_multidim_coords()[:3, :3]
     coord_1, coord_2 = cube.coords()
     with self.assertRaisesRegex(
         ValueError, "Expected coordinate ndim == 1"
     ):
         _ = Mesh.from_coords(coord_1, coord_2)
Пример #3
0
 def test_1_bound(self):
     lon = AuxCoord(points=[0.5, 1.5, 2.5], bounds=[[0], [1], [2]])
     lat = AuxCoord(points=[0, 1, 2], bounds=[[0.5], [1.5], [2.5]])
     with self.assertRaisesRegex(
         ValueError, r"Expected coordinate bounds.shape \(n, >=2\)"
     ):
         _ = Mesh.from_coords(lon, lat)
Пример #4
0
def sample_mesh(n_nodes=None, n_faces=None, n_edges=None):
    """
    Make a test mesh.

    Mesh has faces edges, face-coords and edge-coords, numbers of which can be controlled.

    """
    if n_nodes is None:
        n_nodes = _TEST_N_NODES
    if n_faces is None:
        n_faces = _TEST_N_FACES
    if n_edges is None:
        n_edges = _TEST_N_EDGES
    node_x = AuxCoord(
        1100 + np.arange(n_nodes),
        standard_name="longitude",
        units="degrees_east",
        long_name="long-name",
        var_name="var-name",
        attributes={"a": 1, "b": "c"},
    )
    node_y = AuxCoord(1200 + np.arange(n_nodes), standard_name="latitude")

    # Define a rather arbitrary edge-nodes connectivity.
    # Some nodes are left out, because n_edges*2 < n_nodes.
    conns = np.arange(n_edges * 2, dtype=int)
    # Missing nodes include #0-5, because we add 5.
    conns = ((conns + 5) % n_nodes).reshape((n_edges, 2))
    edge_nodes = Connectivity(conns, cf_role="edge_node_connectivity")
    conns = np.arange(n_edges * 2, dtype=int)

    # Some numbers for the edge coordinates.
    edge_x = AuxCoord(2100 + np.arange(n_edges), standard_name="longitude")
    edge_y = AuxCoord(2200 + np.arange(n_edges), standard_name="latitude")

    # Define a rather arbitrary face-nodes connectivity.
    # Some nodes are left out, because n_faces*n_bounds < n_nodes.
    conns = np.arange(n_faces * _TEST_N_BOUNDS, dtype=int)
    conns = (conns % n_nodes).reshape((n_faces, _TEST_N_BOUNDS))
    face_nodes = Connectivity(conns, cf_role="face_node_connectivity")

    # Some numbers for the edge coordinates.
    face_x = AuxCoord(3100 + np.arange(n_faces), standard_name="longitude")
    face_y = AuxCoord(3200 + np.arange(n_faces), standard_name="latitude")

    mesh = Mesh(
        topology_dimension=2,
        node_coords_and_axes=[(node_x, "x"), (node_y, "y")],
        connectivities=[face_nodes, edge_nodes],
        edge_coords_and_axes=[(edge_x, "x"), (edge_y, "y")],
        face_coords_and_axes=[(face_x, "x"), (face_y, "y")],
    )
    return mesh
Пример #5
0
    def test_connectivity_dim_order(self):
        """
        Test a mesh with some connectivities in the 'other' order.

        This should also create a property with the dimension name.

        """
        # Make a mesh with both faces *and* some edges
        mesh = make_mesh(n_edges=7)
        # Get the face-node and edge-node connectivities
        face_nodes_conn = mesh.face_node_connectivity
        edge_nodes_conn = mesh.edge_node_connectivity
        # Transpose them : N.B. this sets src_dim=1, as it should be.
        nodesfirst_faces_conn = face_nodes_conn.transpose()
        nodesfirst_edges_conn = edge_nodes_conn.transpose()
        # Make a new mesh with both face and edge connectivities 'transposed'.
        mesh2 = Mesh(
            topology_dimension=mesh.topology_dimension,
            node_coords_and_axes=zip(mesh.node_coords, XY_LOCS),
            face_coords_and_axes=zip(mesh.face_coords, XY_LOCS),
            connectivities=[nodesfirst_faces_conn, nodesfirst_edges_conn],
        )

        # Save and snapshot the result
        tempfile_path = self.check_save_mesh(mesh2)
        dims, vars = scan_dataset(tempfile_path)

        # Check shape and dimensions of the associated connectivity variables.
        (mesh_name,) = vars_meshnames(vars)
        mesh_props = vars[mesh_name]
        faceconn_name = mesh_props["face_node_connectivity"]
        edgeconn_name = mesh_props["edge_node_connectivity"]
        faceconn_props = vars[faceconn_name]
        edgeconn_props = vars[edgeconn_name]
        self.assertEqual(
            faceconn_props[_VAR_DIMS], ["Mesh_2d_face_N_nodes", "Mesh2d_face"]
        )
        self.assertEqual(
            edgeconn_props[_VAR_DIMS], ["Mesh_2d_edge_N_nodes", "Mesh2d_edge"]
        )

        # Check the dimension lengths are also as expected
        self.assertEqual(dims["Mesh2d_face"], 2)
        self.assertEqual(dims["Mesh_2d_face_N_nodes"], 4)
        self.assertEqual(dims["Mesh2d_edge"], 7)
        self.assertEqual(dims["Mesh_2d_edge_N_nodes"], 2)

        # the mesh has extra location-dimension properties
        self.assertEqual(mesh_props["face_dimension"], "Mesh2d_face")
        self.assertEqual(mesh_props["edge_dimension"], "Mesh2d_edge")
Пример #6
0
    def _make_test_meshcoord(
        self,
        lazy_sources=False,
        location="face",
        inds_start_index=0,
        inds_location_axis=0,
        facenodes_changes=None,
    ):
        # Construct a miniature face-nodes mesh for testing.
        # NOTE: we will make our connectivity arrays with standard
        # start_index=0 and location_axis=0 :  We only adjust that (if required) when
        # creating the actual connectivities.
        face_nodes_array = np.array(
            [
                [0, 2, 1, 3],
                [1, 3, 10, 13],
                [2, 7, 9, 19],
                [
                    3,
                    4,
                    7,
                    -1,
                ],  # This one has a "missing" point (it's a triangle)
                [8, 1, 7, 2],
            ]
        )
        # Connectivity uses *masked* for missing points.
        face_nodes_array = np.ma.masked_less(face_nodes_array, 0)
        if facenodes_changes:
            facenodes_changes = facenodes_changes.copy()
            facenodes_changes.pop("n_extra_bad_points")
            for indices, value in facenodes_changes.items():
                face_nodes_array[indices] = value

        # Construct a miniature edge-nodes mesh for testing.
        edge_nodes_array = np.array([[0, 2], [1, 3], [1, 4], [3, 7]])
        # Connectivity uses *masked* for missing points.
        edge_nodes_array = np.ma.masked_less(edge_nodes_array, 0)

        n_faces = face_nodes_array.shape[0]
        n_edges = edge_nodes_array.shape[0]
        n_nodes = int(face_nodes_array.max() + 1)
        self.NODECOORDS_BASENUM = 1100.0
        self.EDGECOORDS_BASENUM = 1200.0
        self.FACECOORDS_BASENUM = 1300.0
        node_xs = self.NODECOORDS_BASENUM + np.arange(n_nodes)
        edge_xs = self.EDGECOORDS_BASENUM + np.arange(n_edges)
        face_xs = self.FACECOORDS_BASENUM + np.arange(n_faces)

        # Record all these for re-use in tests
        self.n_faces = n_faces
        self.n_nodes = n_nodes
        self.face_xs = face_xs
        self.node_xs = node_xs
        self.edge_xs = edge_xs
        self.face_nodes_array = face_nodes_array
        self.edge_nodes_array = edge_nodes_array

        # convert source data to Dask arrays if asked.
        if lazy_sources:

            def lazify(arr):
                return da.from_array(arr, chunks=-1, meta=np.ndarray)

            node_xs = lazify(node_xs)
            face_xs = lazify(face_xs)
            edge_xs = lazify(edge_xs)
            face_nodes_array = lazify(face_nodes_array)
            edge_nodes_array = lazify(edge_nodes_array)

        # Build a mesh with this info stored in it.
        co_nodex = AuxCoord(
            node_xs, standard_name="longitude", long_name="node_x", units=1
        )
        co_facex = AuxCoord(
            face_xs, standard_name="longitude", long_name="face_x", units=1
        )
        co_edgex = AuxCoord(
            edge_xs, standard_name="longitude", long_name="edge_x", units=1
        )
        # N.B. the Mesh requires 'Y's as well.
        co_nodey = co_nodex.copy()
        co_nodey.rename("latitude")
        co_nodey.long_name = "node_y"
        co_facey = co_facex.copy()
        co_facey.rename("latitude")
        co_facey.long_name = "face_y"
        co_edgey = co_edgex.copy()
        co_edgey.rename("edge_y")
        co_edgey.long_name = "edge_y"

        face_node_conn = Connectivity(
            inds_start_index
            + (
                face_nodes_array.transpose()
                if inds_location_axis == 1
                else face_nodes_array
            ),
            cf_role="face_node_connectivity",
            long_name="face_nodes",
            start_index=inds_start_index,
            location_axis=inds_location_axis,
        )

        edge_node_conn = Connectivity(
            inds_start_index
            + (
                edge_nodes_array.transpose()
                if inds_location_axis == 1
                else edge_nodes_array
            ),
            cf_role="edge_node_connectivity",
            long_name="edge_nodes",
            start_index=inds_start_index,
            location_axis=inds_location_axis,
        )

        self.mesh = Mesh(
            topology_dimension=2,
            node_coords_and_axes=[(co_nodex, "x"), (co_nodey, "y")],
            connectivities=[face_node_conn, edge_node_conn],
            face_coords_and_axes=[(co_facex, "x"), (co_facey, "y")],
            edge_coords_and_axes=[(co_edgex, "x"), (co_edgey, "y")],
        )

        # Construct a test meshcoord.
        meshcoord = MeshCoord(mesh=self.mesh, location=location, axis="x")
        self.meshcoord = meshcoord
        return meshcoord
Пример #7
0
def sample_mesh(n_nodes=None, n_faces=None, n_edges=None, lazy_values=False):
    """
    Make a test mesh.

    Mesh has nodes, plus faces and/or edges, with face-coords and edge-coords,
    numbers of which can be controlled.

    Args:
    * n_nodes (int or None):
        Number of nodes in mesh. Default is 15.  Cannot be 0.
    * n_edges (int or None):
        Number of edges in mesh. Default is 5.
        If not 0, edge coords and an 'edge_node_connectivity' are included.
    * n_faces (int or None):
        Number of faces in mesh. Default is 3.
        If not 0, face coords and a 'face_node_connectivity' are included.
    * lazy_values (bool):
        If True, all content values of coords and connectivities are lazy.

    """
    if lazy_values:
        import dask.array as da

        arr = da
    else:
        arr = np

    if n_nodes is None:
        n_nodes = _TEST_N_NODES
    if n_faces is None:
        n_faces = _TEST_N_FACES
    if n_edges is None:
        n_edges = _TEST_N_EDGES
    node_x = AuxCoord(
        1100 + arr.arange(n_nodes),
        standard_name="longitude",
        units="degrees_east",
        long_name="long-name",
        var_name="var-name",
        attributes={
            "a": 1,
            "b": "c"
        },
    )
    node_y = AuxCoord(1200 + arr.arange(n_nodes), standard_name="latitude")

    connectivities = []
    if n_edges == 0:
        edge_coords_and_axes = None
    else:
        # Define a rather arbitrary edge-nodes connectivity.
        # Some nodes are left out, because n_edges*2 < n_nodes.
        conns = arr.arange(n_edges * 2, dtype=int)
        # Missing nodes include #0-5, because we add 5.
        conns = ((conns + 5) % n_nodes).reshape((n_edges, 2))
        edge_nodes = Connectivity(conns, cf_role="edge_node_connectivity")
        connectivities.append(edge_nodes)

        edge_x = AuxCoord(2100 + arr.arange(n_edges),
                          standard_name="longitude")
        edge_y = AuxCoord(2200 + arr.arange(n_edges), standard_name="latitude")
        edge_coords_and_axes = [(edge_x, "x"), (edge_y, "y")]

    if n_faces == 0:
        face_coords_and_axes = None
    else:
        # Define a rather arbitrary face-nodes connectivity.
        # Some nodes are left out, because n_faces*n_bounds < n_nodes.
        conns = arr.arange(n_faces * _TEST_N_BOUNDS, dtype=int)
        conns = (conns % n_nodes).reshape((n_faces, _TEST_N_BOUNDS))
        face_nodes = Connectivity(conns, cf_role="face_node_connectivity")
        connectivities.append(face_nodes)

        # Some numbers for the edge coordinates.
        face_x = AuxCoord(3100 + arr.arange(n_faces),
                          standard_name="longitude")
        face_y = AuxCoord(3200 + arr.arange(n_faces), standard_name="latitude")
        face_coords_and_axes = [(face_x, "x"), (face_y, "y")]

    mesh = Mesh(
        topology_dimension=2,
        node_coords_and_axes=[(node_x, "x"), (node_y, "y")],
        connectivities=connectivities,
        edge_coords_and_axes=edge_coords_and_axes,
        face_coords_and_axes=face_coords_and_axes,
    )
    return mesh
Пример #8
0
def build_mesh(
    n_nodes=2,
    n_faces=0,
    n_edges=0,
    nodecoord_xyargs=None,
    edgecoord_xyargs=None,
    facecoord_xyargs=None,
    conn_role_kwargs=None,  # mapping {connectivity-role: connectivity-kwargs}
    mesh_kwargs=None,
):
    """
    Make a test mesh.

    Mesh has faces edges, face-coords and edge-coords, numbers of which can be
    controlled.

    Args:

    * n_nodes, n_faces, n_edges (int):
        Basic dimensions of mesh components.  Zero means no such location.
    * nodecoord_xyargs, edgecoord_xyargs, facecoord_xyargs (pair of dict):
        Pairs (x,y) of settings kwargs, applied after initial creation the
        relevant location coordinates.
    * conn_role_kwargs (dict of string:dict):
        Mapping from cf_role name to settings kwargs for connectivities,
        applied after initially creating them.
    * mesh_kwargs (dict):
        Dictionary of key settings to apply to the Mesh, after creating it.

    """

    def applyargs(coord, kwargs):
        if kwargs:
            for key, val in kwargs.items():
                # kwargs is a dict
                setattr(coord, key, val)

    def apply_xyargs(coords, xyargs):
        if xyargs:
            for coord, kwargs in zip(coords, xyargs):
                # coords and xyargs both iterables : implicitly=(x,y)
                applyargs(coord, kwargs)

    node_coords = [
        AuxCoord(np.arange(n_nodes), standard_name=name) for name in XY_NAMES
    ]
    apply_xyargs(node_coords, nodecoord_xyargs)

    connectivities = {}
    edge_coords = []
    face_coords = []
    topology_dimension = 0
    if n_edges:
        topology_dimension = 1
        connectivities["edge_node_connectivity"] = Connectivity(
            np.zeros((n_edges, 2), np.int32), cf_role="edge_node_connectivity"
        )
        edge_coords = [
            AuxCoord(np.arange(n_edges), standard_name=name)
            for name in XY_NAMES
        ]
        apply_xyargs(edge_coords, edgecoord_xyargs)

    if n_faces:
        topology_dimension = 2
        connectivities["face_node_connectivity"] = Connectivity(
            np.zeros((n_faces, 4), np.int32), cf_role="face_node_connectivity"
        )
        face_coords = [
            AuxCoord(np.arange(n_faces), standard_name=name)
            for name in XY_NAMES
        ]
        apply_xyargs(face_coords, facecoord_xyargs)

    mesh_dims = {"node": n_nodes, "edge": n_edges, "face": n_faces}

    if conn_role_kwargs:
        for role, kwargs in conn_role_kwargs.items():
            if role in connectivities:
                conn = connectivities[role]
            else:
                loc_from, loc_to, _ = role.split("_")
                dims = [mesh_dims[loc] for loc in (loc_from, loc_to)]
                conn = Connectivity(
                    np.zeros(dims, dtype=np.int32), cf_role=role
                )
                connectivities[role] = conn
            applyargs(conn, kwargs)

    mesh = Mesh(
        topology_dimension=topology_dimension,
        node_coords_and_axes=zip(node_coords, XY_LOCS),
        edge_coords_and_axes=zip(edge_coords, XY_LOCS),
        face_coords_and_axes=zip(face_coords, XY_LOCS),
        connectivities=connectivities.values(),
    )
    applyargs(mesh, mesh_kwargs)

    return mesh
Пример #9
0
 def create(self):
     return Mesh.from_coords(self.lon, self.lat)
Пример #10
0
 def test_no_bounds(self):
     lon = AuxCoord(points=[0.5, 1.5, 2.5])
     lat = AuxCoord(points=[0, 1, 2])
     with self.assertRaisesRegex(ValueError, "bounds missing from"):
         _ = Mesh.from_coords(lon, lat)