Skip to content

Commit 2e81be2

Browse files
authored
Extend stock.mesh api (#4389)
* Extend stock.mesh api: optional edges/faces; lazy content; cube nomesh size control. * Fix stock mesh usage. * Remove formatted docstring. * Remove redundant code.
1 parent 9c5f8df commit 2e81be2

File tree

2 files changed

+69
-33
lines changed

2 files changed

+69
-33
lines changed

lib/iris/tests/stock/mesh.py

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,57 +22,90 @@
2222
_TEST_N_BOUNDS = 4
2323

2424

25-
def sample_mesh(n_nodes=None, n_faces=None, n_edges=None):
25+
def sample_mesh(n_nodes=None, n_faces=None, n_edges=None, lazy_values=False):
2626
"""
2727
Make a test mesh.
2828
29-
Mesh has faces edges, face-coords and edge-coords, numbers of which can be controlled.
29+
Mesh has nodes, plus faces and/or edges, with face-coords and edge-coords,
30+
numbers of which can be controlled.
31+
32+
Args:
33+
* n_nodes (int or None):
34+
Number of nodes in mesh. Default is 15. Cannot be 0.
35+
* n_edges (int or None):
36+
Number of edges in mesh. Default is 5.
37+
If not 0, edge coords and an 'edge_node_connectivity' are included.
38+
* n_faces (int or None):
39+
Number of faces in mesh. Default is 3.
40+
If not 0, face coords and a 'face_node_connectivity' are included.
41+
* lazy_values (bool):
42+
If True, all content values of coords and connectivities are lazy.
3043
3144
"""
45+
if lazy_values:
46+
import dask.array as da
47+
48+
arr = da
49+
else:
50+
arr = np
51+
3252
if n_nodes is None:
3353
n_nodes = _TEST_N_NODES
3454
if n_faces is None:
3555
n_faces = _TEST_N_FACES
3656
if n_edges is None:
3757
n_edges = _TEST_N_EDGES
3858
node_x = AuxCoord(
39-
1100 + np.arange(n_nodes),
59+
1100 + arr.arange(n_nodes),
4060
standard_name="longitude",
4161
units="degrees_east",
4262
long_name="long-name",
4363
var_name="var-name",
4464
attributes={"a": 1, "b": "c"},
4565
)
46-
node_y = AuxCoord(1200 + np.arange(n_nodes), standard_name="latitude")
47-
48-
# Define a rather arbitrary edge-nodes connectivity.
49-
# Some nodes are left out, because n_edges*2 < n_nodes.
50-
conns = np.arange(n_edges * 2, dtype=int)
51-
# Missing nodes include #0-5, because we add 5.
52-
conns = ((conns + 5) % n_nodes).reshape((n_edges, 2))
53-
edge_nodes = Connectivity(conns, cf_role="edge_node_connectivity")
54-
conns = np.arange(n_edges * 2, dtype=int)
55-
56-
# Some numbers for the edge coordinates.
57-
edge_x = AuxCoord(2100 + np.arange(n_edges), standard_name="longitude")
58-
edge_y = AuxCoord(2200 + np.arange(n_edges), standard_name="latitude")
59-
60-
# Define a rather arbitrary face-nodes connectivity.
61-
# Some nodes are left out, because n_faces*n_bounds < n_nodes.
62-
conns = np.arange(n_faces * _TEST_N_BOUNDS, dtype=int)
63-
conns = (conns % n_nodes).reshape((n_faces, _TEST_N_BOUNDS))
64-
face_nodes = Connectivity(conns, cf_role="face_node_connectivity")
65-
66-
# Some numbers for the edge coordinates.
67-
face_x = AuxCoord(3100 + np.arange(n_faces), standard_name="longitude")
68-
face_y = AuxCoord(3200 + np.arange(n_faces), standard_name="latitude")
66+
node_y = AuxCoord(1200 + arr.arange(n_nodes), standard_name="latitude")
67+
68+
connectivities = []
69+
if n_edges == 0:
70+
edge_coords_and_axes = None
71+
else:
72+
# Define a rather arbitrary edge-nodes connectivity.
73+
# Some nodes are left out, because n_edges*2 < n_nodes.
74+
conns = arr.arange(n_edges * 2, dtype=int)
75+
# Missing nodes include #0-5, because we add 5.
76+
conns = ((conns + 5) % n_nodes).reshape((n_edges, 2))
77+
edge_nodes = Connectivity(conns, cf_role="edge_node_connectivity")
78+
connectivities.append(edge_nodes)
79+
80+
edge_x = AuxCoord(
81+
2100 + arr.arange(n_edges), standard_name="longitude"
82+
)
83+
edge_y = AuxCoord(2200 + arr.arange(n_edges), standard_name="latitude")
84+
edge_coords_and_axes = [(edge_x, "x"), (edge_y, "y")]
85+
86+
if n_faces == 0:
87+
face_coords_and_axes = None
88+
else:
89+
# Define a rather arbitrary face-nodes connectivity.
90+
# Some nodes are left out, because n_faces*n_bounds < n_nodes.
91+
conns = arr.arange(n_faces * _TEST_N_BOUNDS, dtype=int)
92+
conns = (conns % n_nodes).reshape((n_faces, _TEST_N_BOUNDS))
93+
face_nodes = Connectivity(conns, cf_role="face_node_connectivity")
94+
connectivities.append(face_nodes)
95+
96+
# Some numbers for the edge coordinates.
97+
face_x = AuxCoord(
98+
3100 + arr.arange(n_faces), standard_name="longitude"
99+
)
100+
face_y = AuxCoord(3200 + arr.arange(n_faces), standard_name="latitude")
101+
face_coords_and_axes = [(face_x, "x"), (face_y, "y")]
69102

70103
mesh = Mesh(
71104
topology_dimension=2,
72105
node_coords_and_axes=[(node_x, "x"), (node_y, "y")],
73-
connectivities=[face_nodes, edge_nodes],
74-
edge_coords_and_axes=[(edge_x, "x"), (edge_y, "y")],
75-
face_coords_and_axes=[(face_x, "x"), (face_y, "y")],
106+
connectivities=connectivities,
107+
edge_coords_and_axes=edge_coords_and_axes,
108+
face_coords_and_axes=face_coords_and_axes,
76109
)
77110
return mesh
78111

@@ -92,7 +125,7 @@ def sample_meshcoord(mesh=None, location="face", axis="x", **extra_kwargs):
92125

93126

94127
def sample_mesh_cube(
95-
nomesh=False, n_z=2, with_parts=False, **meshcoord_kwargs
128+
nomesh_faces=None, n_z=2, with_parts=False, **meshcoord_kwargs
96129
):
97130
"""
98131
Create a 2d test cube with 1 'normal' and 1 unstructured dimension (with a Mesh).
@@ -101,8 +134,9 @@ def sample_mesh_cube(
101134
By default, the mesh is provided by :func:`sample_mesh`, so coordinates and connectivity are not realistic.
102135
103136
Kwargs:
104-
* nomesh(bool):
137+
* nomesh_faces (int or None):
105138
If set, don't add MeshCoords, so dim 1 is just a plain anonymous dim.
139+
Set its length to the given value.
106140
* n_z (int):
107141
Length of the 'normal' dim. If 0, it is *omitted*.
108142
* with_parts (bool):
@@ -117,9 +151,10 @@ def sample_mesh_cube(
117151
'parts' is (mesh, dim0-dimcoord, dim1-dimcoord, dim1-auxcoord, x-meshcoord [or None], y-meshcoord [or None]).
118152
119153
"""
154+
nomesh = nomesh_faces is not None
120155
if nomesh:
121156
mesh = None
122-
n_faces = 5
157+
n_faces = nomesh_faces
123158
else:
124159
mesh = meshcoord_kwargs.pop("mesh", None)
125160
if mesh is None:

lib/iris/tests/unit/cube/test_Cube.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2062,8 +2062,9 @@ def _add_test_meshcube(self, nomesh=False, n_z=2, **meshcoord_kwargs):
20622062
its components as properties of the 'self' TestCase.
20632063
20642064
"""
2065+
nomesh_faces = 5 if nomesh else None
20652066
cube, parts = sample_mesh_cube(
2066-
nomesh=nomesh, n_z=n_z, with_parts=True, **meshcoord_kwargs
2067+
nomesh_faces=nomesh_faces, n_z=n_z, with_parts=True, **meshcoord_kwargs
20672068
)
20682069
mesh, zco, mesh_dimco, auxco_x, meshx, meshy = parts
20692070
self.mesh = mesh

0 commit comments

Comments
 (0)