Grid Topology Overview#

Authors: Philip Chmielowiec, Orhan Eroglu

As discussed in our first notebook, UXarray uses the UGRID conventions as a foundation for represented Unstructured Grids. Here we’ll see how to access the underlying dimensions, coordinates, and connectivity variables that are available in UXarray.

Constructing the Grid Topology#

The grid topology is defined as a Grid object in UXarray. A Grid object can be created in different ways.

Constructing through uxarray.open_grid()#

If the intent is to explore only the grid topology instead of having any data sets with it, analyzing data variables, etc., a standalone Grid object can be instantiated as follows:

import uxarray
import uxarray as ux
# Base data path
base_path = "../../test/meshfiles/"

# Grid Path (MPAS Example)
grid_mpas_path = base_path + "/mpas/QU/mesh.QU.1920km.151026.nc"
grid_mpas = ux.open_grid(grid_mpas_path)
grid_mpas
<uxarray.Grid>
Original Grid Type: MPAS
Grid Dimensions:
  * n_node: 320
  * n_edge: 480
  * n_face: 162
  * n_max_face_nodes: 6
  * n_max_face_edges: 6
  * n_max_node_faces: 3
  * two: 2
  * n_nodes_per_face: (162,)
Grid Coordinates (Spherical):
  * node_lon: (320,)
  * node_lat: (320,)
  * edge_lon: (480,)
  * edge_lat: (480,)
  * face_lon: (162,)
  * face_lat: (162,)
Grid Coordinates (Cartesian):
  * node_x: (320,)
  * node_y: (320,)
  * node_z: (320,)
  * edge_x: (480,)
  * edge_y: (480,)
  * edge_z: (480,)
  * face_x: (162,)
  * face_y: (162,)
  * face_z: (162,)
Grid Connectivity Variables:
  * face_node_connectivity: (162, 6)
  * face_edge_connectivity: (162, 6)
  * edge_node_connectivity: (480, 2)
  * edge_face_connectivity: (480, 2)
  * node_face_connectivity: (320, 3)
Grid Descriptor Variables:
  * edge_face_distances: (480,)
  * edge_node_distances: (480,)

Constructing through UxDataset#

If the intent is to have an unstructured grid-aware dataset, i.e. UxDataset, and investigate the grid topology through it instead, the uxgrid property can be used. To be more precise, when a UxDataset object, or likewise UxDataArray object, is generated (e.g. through uxarray.open_dataset()), a Grid object via UxDataset.uxgrid, or UxDataArray.uxgrid, property is also created automatically and assigned to the dataset or variable.

The grid topology can be seen through this property as follows:

# Data File Path (UGRID Example)
grid_ne30_path = base_path + "/ugrid/outCSne30/outCSne30.ug"
data_ne30_path = base_path + "/ugrid/outCSne30/outCSne30_vortex.nc"
uxds = ux.open_dataset(grid_ne30_path, data_ne30_path)
uxds.uxgrid
<uxarray.Grid>
Original Grid Type: UGRID
Grid Dimensions:
  * n_node: 5402
  * n_face: 5400
  * n_max_face_nodes: 4
  * n_nodes_per_face: (5400,)
Grid Coordinates (Spherical):
  * node_lon: (5402,)
  * node_lat: (5402,)
Grid Coordinates (Cartesian):
Grid Connectivity Variables:
  * face_node_connectivity: (5400, 4)
Grid Descriptor Variables:

In addition, a previously-created Grid object can always be assigned to a new UxDataset as its uxgrid property as follows:

uxds_mpas = ux.UxDataset(uxgrid=grid_mpas)
uxds_mpas.uxgrid
<uxarray.Grid>
Original Grid Type: MPAS
Grid Dimensions:
  * n_node: 320
  * n_edge: 480
  * n_face: 162
  * n_max_face_nodes: 6
  * n_max_face_edges: 6
  * n_max_node_faces: 3
  * two: 2
  * n_nodes_per_face: (162,)
Grid Coordinates (Spherical):
  * node_lon: (320,)
  * node_lat: (320,)
  * edge_lon: (480,)
  * edge_lat: (480,)
  * face_lon: (162,)
  * face_lat: (162,)
Grid Coordinates (Cartesian):
  * node_x: (320,)
  * node_y: (320,)
  * node_z: (320,)
  * edge_x: (480,)
  * edge_y: (480,)
  * edge_z: (480,)
  * face_x: (162,)
  * face_y: (162,)
  * face_z: (162,)
Grid Connectivity Variables:
  * face_node_connectivity: (162, 6)
  * face_edge_connectivity: (162, 6)
  * edge_node_connectivity: (480, 2)
  * edge_face_connectivity: (480, 2)
  * node_face_connectivity: (320, 3)
Grid Descriptor Variables:
  * edge_face_distances: (480,)
  * edge_node_distances: (480,)

Grid Attributes#

If our input grid contained additional attributes that were not representable by the UGRID conventions, they would be stored here

uxds.uxgrid.parsed_attrs
{}
uxds_mpas.uxgrid.parsed_attrs
{'on_a_sphere': 'YES',
 'sphere_radius': 1.0,
 'is_periodic': 'NO',
 'history': 'MpasMeshConverter.x base_grids/x1.162.grid.nc base_meshes/x1.162.grid.nc',
 'mesh_spec': '1.0',
 'Conventions': 'MPAS',
 'source': 'MpasMeshConverter.x',
 'file_id': 'rku96q0z66'}

Grid Coordinates#

The coordinates by default are represented in terms of longitude and latitude.

uxds.uxgrid.node_lon
<xarray.DataArray 'node_lon' (n_node: 5402)> Size: 43kB
array([-45.        ,  45.        , 135.        , ..., 141.09968961,
       138.03317102, 135.        ])
Dimensions without coordinates: n_node
uxds.uxgrid.node_lat
<xarray.DataArray 'node_lat' (n_node: 5402)> Size: 43kB
[5402 values with dtype=float64]
Dimensions without coordinates: n_node
Attributes:
    standard_name:  latitude
    long_name:      latitude of 2D mesh nodes
    units:          degrees_north

If you wish to use the Cartesian coordinate system, you can access the following attributes, which will internally construct a set of Cartesian coordinates derived from the previous set.

uxds.uxgrid.node_x
<xarray.DataArray 'node_x' (n_node: 5402)> Size: 43kB
array([ 0.57735027,  0.57735027, -0.57735027, ..., -0.58878977,
       -0.57332232, -0.55611709])
Dimensions without coordinates: n_node
Attributes:
    standard_name:  x
    long name:      Cartesian x location of the corner nodes of each face
    units:          meters
uxds.uxgrid.node_y
<xarray.DataArray 'node_y' (n_node: 5402)> Size: 43kB
array([-0.57735027,  0.57735027,  0.57735027, ...,  0.47509872,
        0.51562103,  0.55611709])
Dimensions without coordinates: n_node
Attributes:
    standard_name:  y
    long name:      Cartesian y location of the corner nodes of each face
    units:          meters
uxds.uxgrid.node_z
<xarray.DataArray 'node_z' (n_node: 5402)> Size: 43kB
array([-0.57735027, -0.57735027, -0.57735027, ...,  0.65391729,
        0.63673894,  0.6176306 ])
Dimensions without coordinates: n_node
Attributes:
    standard_name:  z
    long name:      Cartesian z location of the corner nodes of each face
    units:          meters

Grid Connectivity#

Connectivity variables are used to describe how various geometric elements (nodes, faces, edges) can be manipulated and interconnected to represent the topology of the unstructured grid.

As described in the UGRID conventions, these connectivity variables are stored as integer arrays and may contain a Fill Value. UXarray standardizes both of these at the data loading step, meaning that the data type and fill value can always be guaranteed to be the following:

ux.INT_DTYPE
numpy.int64
ux.INT_FILL_VALUE
-9223372036854775808

Below we can see how to access these connectivity variables.

uxds.uxgrid.face_node_connectivity
<xarray.DataArray 'face_node_connectivity' (n_face: 5400, n_max_face_nodes: 4)> Size: 173kB
array([[   0,    8,  356,  124],
       [   8,    9,  357,  356],
       [   9,   10,  358,  357],
       ...,
       [5399, 5400,  299,  300],
       [5400, 5401,  298,  299],
       [5401,  297,    6,  298]])
Dimensions without coordinates: n_face, n_max_face_nodes
Attributes:
    cf_role:      face_node_connectivity
    start_index:  0
    _FillValue:   -9223372036854775808
uxds.uxgrid.n_nodes_per_face
<xarray.DataArray 'n_nodes_per_face' (n_face: 5400)> Size: 43kB
array([4, 4, 4, ..., 4, 4, 4])
Dimensions without coordinates: n_face
Attributes:
    cf_role:    n_nodes_per_face
    long name:  Number of nodes per face
    dtype:      <class 'numpy.int64'>
uxds.uxgrid
<uxarray.Grid>
Original Grid Type: UGRID
Grid Dimensions:
  * n_node: 5402
  * n_face: 5400
  * n_max_face_nodes: 4
  * n_nodes_per_face: (5400,)
Grid Coordinates (Spherical):
  * node_lon: (5402,)
  * node_lat: (5402,)
Grid Coordinates (Cartesian):
  * node_x: (5402,)
  * node_y: (5402,)
  * node_z: (5402,)
Grid Connectivity Variables:
  * face_node_connectivity: (5400, 4)
Grid Descriptor Variables:

As we can see above, these are the only two connectivity variables listed. In addition to these, UXarray provides support for constructing additional connectivity variables.

uxds.uxgrid.edge_node_connectivity
<xarray.DataArray 'edge_node_connectivity' (n_edge: 10800, two: 2)> Size: 173kB
array([[   0,    8],
       [   0,  123],
       [   0,  124],
       ...,
       [5398, 5399],
       [5399, 5400],
       [5400, 5401]])
Dimensions without coordinates: n_edge, two
Attributes:
    cf_role:          edge_node_connectivity
    long name:        Maps every edge to the two nodes that it connects.
    start_index:      0
    dtype:            <class 'numpy.int64'>
    inverse_indices:  [  0  25 369 ...  19  20 886]
    fill_value_mask:  [False False False ... False False False]
uxds.uxgrid.face_edge_connectivity
<xarray.DataArray 'face_edge_connectivity' (n_face: 5400, n_max_face_edges: 4)> Size: 173kB
array([[    0,    25,   369,     2],
       [   24,    28,  1056,    25],
       [   27,    31,  1058,    28],
       ...,
       [10798,   889,   887,   892],
       [10799,   886,   884,   889],
       [  883,    19,    20,   886]])
Dimensions without coordinates: n_face, n_max_face_edges
Attributes:
    cf_role:      face_edge_connectivity
    long name:    Maps every face to its edges.
    start_index:  0
    _FillValue:   -9223372036854775808
    dtype:        <class 'numpy.int64'>
uxds.uxgrid
<uxarray.Grid>
Original Grid Type: UGRID
Grid Dimensions:
  * n_node: 5402
  * n_edge: 10800
  * n_face: 5400
  * n_max_face_nodes: 4
  * n_max_face_edges: 4
  * two: 2
  * n_nodes_per_face: (5400,)
Grid Coordinates (Spherical):
  * node_lon: (5402,)
  * node_lat: (5402,)
Grid Coordinates (Cartesian):
  * node_x: (5402,)
  * node_y: (5402,)
  * node_z: (5402,)
Grid Connectivity Variables:
  * face_node_connectivity: (5400, 4)
  * face_edge_connectivity: (5400, 4)
  * edge_node_connectivity: (10800, 2)
Grid Descriptor Variables:

These additional variables are constructed upon calling their respective attributes and are now stored under the uxgrid property. Additionally, the Mesh2_node_cart_x, Mesh2_node_cart_y, and Mesh2_node_cart_z that we constructed earlier are now also shown here.

Grid Dimensions#

uxds.uxgrid.n_node
5402
uxds.uxgrid.n_edge
10800
uxds.uxgrid.n_face
5400
uxds.uxgrid.n_max_face_nodes
4
uxds.uxgrid.n_max_face_edges
4