Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mesh nonexperimental #6061

Merged
merged 7 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 39 additions & 39 deletions docs/src/further_topics/ugrid/data_model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ How Iris Represents This
.. seealso::

Remember this is a prose summary. Precise documentation is at:
:mod:`iris.experimental.ugrid`.
:mod:`iris.ugrid`.

.. note::

Expand All @@ -310,7 +310,7 @@ The Basics
The Iris :class:`~iris.cube.Cube` has several new members:

* | :attr:`~iris.cube.Cube.mesh`
| The :class:`iris.experimental.ugrid.MeshXY` that describes the
| The :class:`iris.ugrid.MeshXY` that describes the
:class:`~iris.cube.Cube`\'s horizontal geography.
* | :attr:`~iris.cube.Cube.location`
| ``node``/``edge``/``face`` - the mesh element type with which this
Expand All @@ -320,10 +320,10 @@ The Iris :class:`~iris.cube.Cube` has several new members:
indexes over the horizontal :attr:`~iris.cube.Cube.data` positions.
These members will all be ``None`` for a :class:`~iris.cube.Cube` with no
associated :class:`~iris.experimental.ugrid.MeshXY`.
associated :class:`~iris.ugrid.MeshXY`.

This :class:`~iris.cube.Cube`\'s unstructured dimension has multiple attached
:class:`iris.experimental.ugrid.MeshCoord`\s (one for each axis e.g.
:class:`iris.ugrid.MeshCoord`\s (one for each axis e.g.
``x``/``y``), which can be used to infer the points and bounds of any index on
the :class:`~iris.cube.Cube`\'s unstructured dimension.

Expand All @@ -333,7 +333,7 @@ the :class:`~iris.cube.Cube`\'s unstructured dimension.

from iris.coords import AuxCoord, DimCoord
from iris.cube import Cube
from iris.experimental.ugrid import Connectivity, MeshXY
from iris.ugrid import Connectivity, MeshXY

node_x = AuxCoord(
points=[0.0, 5.0, 0.0, 5.0, 8.0],
Expand Down Expand Up @@ -422,38 +422,38 @@ The Detail
----------
How UGRID information is stored
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | :class:`iris.experimental.ugrid.MeshXY`
* | :class:`iris.ugrid.MeshXY`
| Contains all information about the mesh.
| Includes:
* | :attr:`~iris.experimental.ugrid.MeshXY.topology_dimension`
* | :attr:`~iris.ugrid.MeshXY.topology_dimension`
| The maximum dimensionality of shape (1D=edge, 2D=face) supported
by this :class:`~iris.experimental.ugrid.MeshXY`. Determines which
:class:`~iris.experimental.ugrid.Connectivity`\s are required/optional
by this :class:`~iris.ugrid.MeshXY`. Determines which
:class:`~iris.ugrid.Connectivity`\s are required/optional
(see below).
* 1-3 collections of :class:`iris.coords.AuxCoord`\s:

* | **Required**: :attr:`~iris.experimental.ugrid.MeshXY.node_coords`
* | **Required**: :attr:`~iris.ugrid.MeshXY.node_coords`
| The nodes that are the basis for the mesh.
* | Optional: :attr:`~iris.experimental.ugrid.MeshXY.edge_coords`,
:attr:`~iris.experimental.ugrid.MeshXY.face_coords`
* | Optional: :attr:`~iris.ugrid.Mesh.edge_coords`,
:attr:`~iris.ugrid.MeshXY.face_coords`
| For indicating the 'centres' of the edges/faces.
| **NOTE:** generating a :class:`~iris.experimental.ugrid.MeshCoord` from
a :class:`~iris.experimental.ugrid.MeshXY` currently (``Jan 2022``)
| **NOTE:** generating a :class:`~iris.ugrid.MeshCoord` from
a :class:`~iris.ugrid.MeshXY` currently (``Jan 2022``)
requires centre coordinates for the given ``location``; to be rectified
in future.
* 1 or more :class:`iris.experimental.ugrid.Connectivity`\s:
* 1 or more :class:`iris.ugrid.Connectivity`\s:

* | **Required for 1D (edge) elements**:
:attr:`~iris.experimental.ugrid.MeshXY.edge_node_connectivity`
:attr:`~iris.ugrid.MeshXY.edge_node_connectivity`
| Define the edges by connecting nodes.
* | **Required for 2D (face) elements**:
:attr:`~iris.experimental.ugrid.MeshXY.face_node_connectivity`
:attr:`~iris.ugrid.MeshXY.face_node_connectivity`
| Define the faces by connecting nodes.
* Optional: any other connectivity type. See
:attr:`iris.experimental.ugrid.mesh.Connectivity.UGRID_CF_ROLES` for the
:attr:`iris.ugrid.mesh.Connectivity.UGRID_CF_ROLES` for the
full list of types.

.. doctest:: ugrid_summaries
Expand All @@ -480,54 +480,54 @@ How UGRID information is stored
<AuxCoord: latitude / (degrees_north) [...] shape(2,)>
long_name: 'my_mesh'

* | :class:`iris.experimental.ugrid.MeshCoord`
* | :class:`iris.ugrid.MeshCoord`
| Described in detail in `MeshCoords`_.
| Stores the following information:
* | :attr:`~iris.experimental.ugrid.MeshCoord.mesh`
| The :class:`~iris.experimental.ugrid.MeshXY` associated with this
:class:`~iris.experimental.ugrid.MeshCoord`. This determines the
* | :attr:`~iris.ugrid.MeshCoord.mesh`
| The :class:`~iris.ugrid.MeshXY` associated with this
:class:`~iris.ugrid.MeshCoord`. This determines the
:attr:`~iris.cube.Cube.mesh` attribute of any :class:`~iris.cube.Cube`
this :class:`~iris.experimental.ugrid.MeshCoord` is attached to (see
this :class:`~iris.ugrid.MeshCoord` is attached to (see
`The Basics`_)
* | :attr:`~iris.experimental.ugrid.MeshCoord.location`
* | :attr:`~iris.ugrid.MeshCoord.location`
| ``node``/``edge``/``face`` - the element detailed by this
:class:`~iris.experimental.ugrid.MeshCoord`. This determines the
:class:`~iris.ugrid.MeshCoord`. This determines the
:attr:`~iris.cube.Cube.location` attribute of any
:class:`~iris.cube.Cube` this
:class:`~iris.experimental.ugrid.MeshCoord` is attached to (see
:class:`~iris.ugrid.MeshCoord` is attached to (see
`The Basics`_).
.. _ugrid MeshCoords:

MeshCoords
~~~~~~~~~~
Links a :class:`~iris.cube.Cube` to a :class:`~iris.experimental.ugrid.MeshXY` by
Links a :class:`~iris.cube.Cube` to a :class:`~iris.ugrid.MeshXY` by
attaching to the :class:`~iris.cube.Cube`\'s unstructured dimension, in the
same way that all :class:`~iris.coords.Coord`\s attach to
:class:`~iris.cube.Cube` dimensions. This allows a single
:class:`~iris.cube.Cube` to have a combination of unstructured and structured
dimensions (e.g. horizontal mesh plus vertical levels and a time series),
using the same logic for every dimension.

:class:`~iris.experimental.ugrid.MeshCoord`\s are instantiated using a given
:class:`~iris.experimental.ugrid.MeshXY`, ``location``
:class:`~iris.ugrid.MeshCoord`\s are instantiated using a given
:class:`~iris.ugrid.MeshXY`, ``location``
("node"/"edge"/"face") and ``axis``. The process interprets the
:class:`~iris.experimental.ugrid.MeshXY`\'s
:attr:`~iris.experimental.ugrid.MeshXY.node_coords` and if appropriate the
:attr:`~iris.experimental.ugrid.MeshXY.edge_node_connectivity`/
:attr:`~iris.experimental.ugrid.MeshXY.face_node_connectivity` and
:attr:`~iris.experimental.ugrid.MeshXY.edge_coords`/
:attr:`~iris.experimental.ugrid.MeshXY.face_coords`
:class:`~iris.ugrid.MeshXY`\'s
:attr:`~iris.ugrid.MeshXY.node_coords` and if appropriate the
:attr:`~iris.ugrid.MeshXY.edge_node_connectivity`/
:attr:`~iris.ugrid.MeshXY.face_node_connectivity` and
:attr:`~iris.ugrid.MeshXY.edge_coords`/
:attr:`~iris.ugrid.MeshXY.face_coords`
to produce a :class:`~iris.coords.Coord`
:attr:`~iris.coords.Coord.points` and :attr:`~iris.coords.Coord.bounds`
representation of all the :class:`~iris.experimental.ugrid.MeshXY`\'s
representation of all the :class:`~iris.ugrid.MeshXY`\'s
nodes/edges/faces for the given axis.

The method :meth:`iris.experimental.ugrid.MeshXY.to_MeshCoords` is available to
create a :class:`~iris.experimental.ugrid.MeshCoord` for
every axis represented by that :class:`~iris.experimental.ugrid.MeshXY`,
The method :meth:`iris.ugrid.MeshXY.to_MeshCoords` is available to
create a :class:`~iris.ugrid.MeshCoord` for
every axis represented by that :class:`~iris.ugrid.MeshXY`,
given only the ``location`` argument

.. doctest:: ugrid_summaries
Expand Down
2 changes: 1 addition & 1 deletion docs/src/further_topics/ugrid/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Iris includes specialised handling of mesh-located data (as opposed to
grid-located data). Iris and its :ref:`partner packages <ugrid partners>` are
designed to make working with mesh-located data as simple as possible, with new
capabilities being added all the time. More detail is in this section and in
the :mod:`iris.experimental.ugrid` API documentation.
the :mod:`iris.ugrid` API documentation.

This mesh support is based on the `CF-UGRID Conventions`__; UGRID-conformant
meshes + data can be loaded from a file into Iris' data model, and meshes +
Expand Down
70 changes: 35 additions & 35 deletions docs/src/further_topics/ugrid/operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ subsequent example operations on this page.
>>> import numpy as np

>>> from iris.coords import AuxCoord
>>> from iris.experimental.ugrid import Connectivity, MeshXY
>>> from iris.ugrid import Connectivity, MeshXY

# Going to create the following mesh
# (node indices are shown to aid understanding):
Expand Down Expand Up @@ -143,8 +143,8 @@ Making a Cube (with a Mesh)
.. rubric:: |tagline: making a cube|

Creating a :class:`~iris.cube.Cube` is unchanged; the
:class:`~iris.experimental.ugrid.MeshXY` is linked via a
:class:`~iris.experimental.ugrid.MeshCoord` (see :ref:`ugrid MeshCoords`):
:class:`~iris.ugrid.MeshXY` is linked via a
:class:`~iris.ugrid.MeshCoord` (see :ref:`ugrid MeshCoords`):

.. dropdown:: Code
:icon: code
Expand Down Expand Up @@ -205,7 +205,7 @@ Save
.. note:: UGRID saving support is limited to the NetCDF file format.

The Iris saving process automatically detects if the :class:`~iris.cube.Cube`
has an associated :class:`~iris.experimental.ugrid.MeshXY` and automatically
has an associated :class:`~iris.ugrid.MeshXY` and automatically
saves the file in a UGRID-conformant format:

.. dropdown:: Code
Expand Down Expand Up @@ -282,8 +282,8 @@ saves the file in a UGRID-conformant format:
}
<BLANKLINE>

The :func:`iris.experimental.ugrid.save_mesh` function allows
:class:`~iris.experimental.ugrid.MeshXY`\es to be saved to file without
The :func:`iris.ugrid.save_mesh` function allows
:class:`~iris.ugrid.MeshXY`\es to be saved to file without
associated :class:`~iris.cube.Cube`\s:

.. dropdown:: Code
Expand All @@ -293,7 +293,7 @@ associated :class:`~iris.cube.Cube`\s:

>>> from subprocess import run

>>> from iris.experimental.ugrid import save_mesh
>>> from iris.ugrid import save_mesh

>>> mesh_path = "my_mesh.nc"
>>> save_mesh(my_mesh, mesh_path)
Expand Down Expand Up @@ -356,15 +356,15 @@ Load
While Iris' UGRID support remains :mod:`~iris.experimental`, parsing UGRID when
loading a file remains **optional**. To load UGRID data from a file into the
Iris mesh data model, use the
:const:`iris.experimental.ugrid.PARSE_UGRID_ON_LOAD` context manager:
:const:`iris.ugrid.PARSE_UGRID_ON_LOAD` context manager:

.. dropdown:: Code
:icon: code

.. doctest:: ugrid_operations

>>> from iris import load
>>> from iris.experimental.ugrid import PARSE_UGRID_ON_LOAD
>>> from iris.ugrid import PARSE_UGRID_ON_LOAD

>>> with PARSE_UGRID_ON_LOAD.context():
... loaded_cubelist = load(cubelist_path)
Expand Down Expand Up @@ -412,23 +412,23 @@ etcetera:
.. note::

We recommend caution if constraining on coordinates associated with a
:class:`~iris.experimental.ugrid.MeshXY`. An individual coordinate value
:class:`~iris.ugrid.MeshXY`. An individual coordinate value
might not be shared by any other data points, and using a coordinate range
will demand notably higher performance given the size of the dimension
versus structured grids
(:ref:`see the data model detail <ugrid implications>`).

The :func:`iris.experimental.ugrid.load_mesh` and
:func:`~iris.experimental.ugrid.load_meshes` functions allow only
:class:`~iris.experimental.ugrid.MeshXY`\es to be loaded from a file without
The :func:`iris.ugrid.load_mesh` and
:func:`~iris.ugrid.load_meshes` functions allow only
:class:`~iris.ugrid.MeshXY`\es to be loaded from a file without
creating any associated :class:`~iris.cube.Cube`\s:

.. dropdown:: Code
:icon: code

.. doctest:: ugrid_operations

>>> from iris.experimental.ugrid import load_mesh
>>> from iris.ugrid import load_mesh

>>> with PARSE_UGRID_ON_LOAD.context():
... loaded_mesh = load_mesh(cubelist_path)
Expand Down Expand Up @@ -493,7 +493,7 @@ GeoVista :external+geovista:doc:`generated/gallery/index`.
>>> from iris import load_cube, sample_data_path
>>> from iris.experimental.geovista import cube_to_polydata
>>> from iris.experimental.ugrid import PARSE_UGRID_ON_LOAD
>>> from iris.ugrid import PARSE_UGRID_ON_LOAD
>>> with PARSE_UGRID_ON_LOAD.context():
... sample_mesh_cube = load_cube(sample_data_path("mesh_C4_synthetic_float.nc"))
Expand Down Expand Up @@ -541,11 +541,11 @@ As described in :doc:`data_model`, indexing for a range along a
:class:`~iris.cube.Cube`\'s :meth:`~iris.cube.Cube.mesh_dim` will not provide
a contiguous region, since **position on the unstructured dimension is
unrelated to spatial position**. This means that subsetted
:class:`~iris.experimental.ugrid.MeshCoord`\s cannot be reliably interpreted
as intended, and subsetting a :class:`~iris.experimental.ugrid.MeshCoord` is
:class:`~iris.ugrid.MeshCoord`\s cannot be reliably interpreted
as intended, and subsetting a :class:`~iris.ugrid.MeshCoord` is
therefore set to return an :class:`~iris.coords.AuxCoord` instead - breaking
the link between :class:`~iris.cube.Cube` and
:class:`~iris.experimental.ugrid.MeshXY`:
:class:`~iris.ugrid.MeshXY`:
.. dropdown:: Code
:icon: code
Expand Down Expand Up @@ -595,7 +595,7 @@ below:
>>> from geovista.geodesic import BBox
>>> from iris import load_cube, sample_data_path
>>> from iris.experimental.geovista import cube_to_polydata, extract_unstructured_region
>>> from iris.experimental.ugrid import PARSE_UGRID_ON_LOAD
>>> from iris.ugrid import PARSE_UGRID_ON_LOAD
>>> with PARSE_UGRID_ON_LOAD.context():
... sample_mesh_cube = load_cube(sample_data_path("mesh_C4_synthetic_float.nc"))
Expand Down Expand Up @@ -667,7 +667,7 @@ with the
>>> from esmf_regrid.experimental.unstructured_scheme import MeshToGridESMFRegridder
>>> from iris import load, load_cube
>>> from iris.experimental.ugrid import PARSE_UGRID_ON_LOAD
>>> from iris.ugrid import PARSE_UGRID_ON_LOAD
# You could also download these files from github.com/SciTools/iris-test-data.
>>> from iris.tests import get_data_path
Expand Down Expand Up @@ -751,7 +751,7 @@ with the
The initialisation process is computationally expensive so we use caching to
improve performance. Once a regridder has been initialised, it can be used on
any :class:`~iris.cube.Cube` which has been defined on the same
:class:`~iris.experimental.ugrid.MeshXY` (or on the same **grid** in the case of
:class:`~iris.ugrid.MeshXY` (or on the same **grid** in the case of
:class:`~esmf_regrid.experimental.unstructured_scheme.GridToMeshESMFRegridder`).
Since calling a regridder is usually a lot faster than initialising, reusing
regridders can save a lot of time. We can demonstrate the reuse of the
Expand Down Expand Up @@ -819,19 +819,19 @@ Equality
.. rubric:: |tagline: equality|
:class:`~iris.experimental.ugrid.MeshXY` comparison is supported, and comparing
two ':class:`~iris.experimental.ugrid.MeshXY`-:class:`~iris.cube.Cube`\s' will
:class:`~iris.ugrid.MeshXY` comparison is supported, and comparing
two ':class:`~iris.ugrid.MeshXY`-:class:`~iris.cube.Cube`\s' will
include a comparison of the respective
:class:`~iris.experimental.ugrid.MeshXY`\es, with no extra action needed by the
:class:`~iris.ugrid.MeshXY`\es, with no extra action needed by the
user.
.. note::
Keep an eye on memory demand when comparing large
:class:`~iris.experimental.ugrid.MeshXY`\es, but note that
:class:`~iris.experimental.ugrid.MeshXY`\ equality is enabled for lazy
:class:`~iris.ugrid.MeshXY`\es, but note that
:class:`~iris.ugrid.MeshXY`\ equality is enabled for lazy
processing (:doc:`/userguide/real_and_lazy_data`), so if the
:class:`~iris.experimental.ugrid.MeshXY`\es being compared are lazy the
:class:`~iris.ugrid.MeshXY`\es being compared are lazy the
process will use less memory than their total size.
Combining Cubes
Expand All @@ -842,23 +842,23 @@ Combining Cubes
Merging or concatenating :class:`~iris.cube.Cube`\s (described in
:doc:`/userguide/merge_and_concat`) with two different
:class:`~iris.experimental.ugrid.MeshXY`\es is not possible - a
:class:`~iris.ugrid.MeshXY`\es is not possible - a
:class:`~iris.cube.Cube` must be associated with just a single
:class:`~iris.experimental.ugrid.MeshXY`, and merge/concatenate are not yet
capable of combining multiple :class:`~iris.experimental.ugrid.MeshXY`\es into
:class:`~iris.ugrid.MeshXY`, and merge/concatenate are not yet
capable of combining multiple :class:`~iris.ugrid.MeshXY`\es into
one.

:class:`~iris.cube.Cube`\s that include
:class:`~iris.experimental.ugrid.MeshCoord`\s can still be merged/concatenated
:class:`~iris.ugrid.MeshCoord`\s can still be merged/concatenated
on dimensions other than the :meth:`~iris.cube.Cube.mesh_dim`, since such
:class:`~iris.cube.Cube`\s will by definition share the same
:class:`~iris.experimental.ugrid.MeshXY`.
:class:`~iris.ugrid.MeshXY`.

.. seealso::

You may wish to investigate
:func:`iris.experimental.ugrid.recombine_submeshes`, which can be used
for a very specific type of :class:`~iris.experimental.ugrid.MeshXY`
:func:`iris.ugrid.recombine_submeshes`, which can be used
for a very specific type of :class:`~iris.ugrid.MeshXY`
combination not detailed here.

Arithmetic
Expand All @@ -869,7 +869,7 @@ Arithmetic

Cube Arithmetic (described in :doc:`/userguide/cube_maths`)
has been extended to handle :class:`~iris.cube.Cube`\s that include
:class:`~iris.experimental.ugrid.MeshCoord`\s, and hence have a ``cube.mesh``.
:class:`~iris.ugrid.MeshCoord`\s, and hence have a ``cube.mesh``.

Cubes with meshes can be combined in arithmetic operations like
"ordinary" cubes. They can combine with other cubes without that mesh
Expand Down
Loading
Loading