.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/network_gridder.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_network_gridder.py: Gridding Ugrid1d Network Data to 2D Grids ========================================= In this example, we demonstrate how to interpolate and grid data from a network of line elements (UGRID1D) to a 2D structured grid. We'll cover the following xugrid techniques: * Creating Ugrid1d networks from node and edge arrays * Finding intersections between 1D and 2D grid edges * Refining networks by inserting intersection points * Topology-aware Laplace interpolation along networks * Converting node data to edge data * Regridding from 1D networks to 2D grids using NetworkGridder * Visualization of mixed 1D and 2D grids .. GENERATED FROM PYTHON SOURCE LINES 19-21 We'll start by setting up the structured grid first and converting it to a Ugrid2d grid. .. GENERATED FROM PYTHON SOURCE LINES 21-52 .. code-block:: Python import numpy as np import xarray as xr import xugrid as xu def make_structured_grid(nrow, ncol, dx, dy): if dy >= 0: raise ValueError("dy must be negative.") shape = nrow, ncol xmin = 0.0 xmax = dx * ncol ymin = 0.0 ymax = abs(dy) * nrow dims = ("y", "x") y = np.arange(ymax, ymin, dy) + 0.5 * dy x = np.arange(xmin, xmax, dx) + 0.5 * dx coords = {"y": y, "x": x} return xr.DataArray(np.ones(shape, dtype=np.int32), coords=coords, dims=dims) structured_grid = make_structured_grid(10, 10, 1.5, -1.5) uda = xu.UgridDataArray.from_structured2d(structured_grid) ugrid2d = uda.ugrid.grid uda .. raw:: html
<xarray.DataArray (mesh2d_nFaces: 100)> Size: 400B
    array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
           1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
           1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
           1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
           1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
    Coordinates:
      * mesh2d_nFaces  (mesh2d_nFaces) int64 800B 0 1 2 3 4 5 ... 94 95 96 97 98 99


.. GENERATED FROM PYTHON SOURCE LINES 53-56 Next, we create a 1D network. This network consists of 5 nodes and 4 edges. At node 2 the network forks to two branches. The data is located assigned to the nodes. .. GENERATED FROM PYTHON SOURCE LINES 57-83 .. code-block:: Python node_xy = np.array( [ [0.0, 0.0], [5.0, 5.0], [10.0, 5.0], [15.0, 0.0], [15.0, 10.0], ] ) edge_nodes = np.array( [ [0, 1], [1, 2], [2, 3], [2, 4], ] ) network = xu.Ugrid1d(*node_xy.T, -1, edge_nodes) data = xr.DataArray( np.array([1, 1.5, 2, 4, -4], dtype=float), dims=(network.node_dimension,) ) uda_1d = xu.UgridDataArray(data, grid=network) uda_1d .. raw:: html
<xarray.DataArray (network1d_nNodes: 5)> Size: 40B
    array([ 1. ,  1.5,  2. ,  4. , -4. ])
    Coordinates:
      * network1d_nNodes  (network1d_nNodes) int64 40B 0 1 2 3 4


.. GENERATED FROM PYTHON SOURCE LINES 84-87 Let's plot the 1D network on top of the 2D grid. The 1D network is shown in light gray, the 2D grid in dark gray. The network's nodes are colored by data values. .. GENERATED FROM PYTHON SOURCE LINES 88-93 .. code-block:: Python uda_1d.ugrid.plot(zorder=10) uda_1d.ugrid.grid.plot(color="black", alpha=0.5) ugrid2d.plot(color="gray", alpha=0.5) .. image-sg:: /examples/images/sphx_glr_network_gridder_001.png :alt: network gridder :srcset: /examples/images/sphx_glr_network_gridder_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 94-100 Intersect edges --------------- First, we need to find the intersection points between the edges of the network and the 2D grid. We can do this by using the :meth:`xugrid.Ugrid1D.intersect_edges` method. .. GENERATED FROM PYTHON SOURCE LINES 101-105 .. code-block:: Python edges_coords = ugrid2d.node_coordinates[ugrid2d.edge_node_connectivity] _, _, intersections_xy = network.intersect_edges(edges_coords) .. GENERATED FROM PYTHON SOURCE LINES 106-107 Let's look at the intersection points. .. GENERATED FROM PYTHON SOURCE LINES 107-119 .. code-block:: Python import matplotlib.pyplot as plt fig, ax = plt.subplots() ugrid2d.plot( ax=ax, color="gray", alpha=0.5, ) plt.scatter(*intersections_xy.T) .. image-sg:: /examples/images/sphx_glr_network_gridder_002.png :alt: network gridder :srcset: /examples/images/sphx_glr_network_gridder_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 120-123 Let's take a look at the individual values. We can see that the intersection points are located at the vertices of the 2D grid. This introduces duplicate intersection points. .. GENERATED FROM PYTHON SOURCE LINES 123-126 .. code-block:: Python intersections_xy .. rst-class:: sphx-glr-script-out .. code-block:: none array([[14. , 9. ], [13.5, 8.5], [12.5, 7.5], [12. , 7. ], [ 4.5, 4.5], [ 6. , 5. ], [ 7.5, 5. ], [ 9. , 5. ], [11. , 6. ], [10.5, 4.5], [10.5, 5.5], [ 4.5, 4.5], [ 3. , 3. ], [10.5, 4.5], [12. , 3. ], [ 3. , 3. ], [ 1.5, 1.5], [12. , 3. ], [13.5, 1.5], [ 1.5, 1.5], [ 0. , 0. ], [13.5, 1.5]]) .. GENERATED FROM PYTHON SOURCE LINES 127-130 Because the line interesects cell vertices, we have duplicate intersection points. Remove duplicates by finding the uniques, as duplicates are not allowed in the network refinement we'll do in the next step. .. GENERATED FROM PYTHON SOURCE LINES 130-135 .. code-block:: Python _intersections_xy = np.unique(intersections_xy, axis=0) _intersections_xy .. rst-class:: sphx-glr-script-out .. code-block:: none array([[ 0. , 0. ], [ 1.5, 1.5], [ 3. , 3. ], [ 4.5, 4.5], [ 6. , 5. ], [ 7.5, 5. ], [ 9. , 5. ], [10.5, 4.5], [10.5, 5.5], [11. , 6. ], [12. , 3. ], [12. , 7. ], [12.5, 7.5], [13.5, 1.5], [13.5, 8.5], [14. , 9. ]]) .. GENERATED FROM PYTHON SOURCE LINES 136-141 Refining the network -------------------- Let's refine the network by the intersection points. This will create new nodes at the intersection points and add edges between the new nodes and the original .. GENERATED FROM PYTHON SOURCE LINES 142-149 .. code-block:: Python refined_network, refined_node_index = network.refine_by_vertices( _intersections_xy, return_index=True ) refined_network .. rst-class:: sphx-glr-script-out .. code-block:: none Size: 632B Dimensions: (network1d_nEdges: 19, two: 2, network1d_nNodes: 20) Coordinates: network1d_node_x (network1d_nNodes) float64 160B 0.0 5.0 ... 13.5 14.0 network1d_node_y (network1d_nNodes) float64 160B 0.0 5.0 ... 8.5 9.0 Dimensions without coordinates: network1d_nEdges, two, network1d_nNodes Data variables: network1d int64 8B 0 network1d_edge_nodes (network1d_nEdges, two) int64 304B 0 5 5 6 ... 19 19 4 Attributes: Conventions: CF-1.9 UGRID-1.0 .. GENERATED FROM PYTHON SOURCE LINES 150-152 We'll create a new UgridDataArray with the refined network. The data will be set to NaN at the refined nodes. The original data will be set to the original nodes. .. GENERATED FROM PYTHON SOURCE LINES 152-164 .. code-block:: Python refined_data = xr.DataArray( np.empty_like(refined_network.node_x), dims=(refined_network.node_dimension,) ) uda_1d_refined = xu.UgridDataArray(refined_data, grid=refined_network) # Set data node_dim = uda_1d.ugrid.grid.node_dimension uda_1d_refined.data[uda_1d[node_dim].data] = uda_1d.data uda_1d_refined.data[refined_node_index] = np.nan uda_1d_refined .. raw:: html
<xarray.DataArray (network1d_nNodes: 20)> Size: 160B
    array([ 1. ,  1.5,  2. ,  4. , -4. ,  nan,  nan,  nan,  nan,  nan,  nan,
            nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan])
    Coordinates:
      * network1d_nNodes  (network1d_nNodes) int64 160B 0 1 2 3 4 ... 15 16 17 18 19


.. GENERATED FROM PYTHON SOURCE LINES 165-171 Interpolation ------------- Next, interpolate the data to the refined nodes, we can do this with a laplace interpolation. This nicely interpolates the data along the network: Notice that the two branches on the right-hand side are interpolated separately. .. GENERATED FROM PYTHON SOURCE LINES 172-180 .. code-block:: Python uda_1d_interpolated = uda_1d_refined.ugrid.laplace_interpolate() fig, ax = plt.subplots() uda_1d_interpolated.ugrid.plot(ax=ax, zorder=10) uda_1d_interpolated.ugrid.grid.plot(ax=ax, color="black", alpha=0.5, zorder=2) ugrid2d.plot(ax=ax, color="gray", alpha=0.5, zorder=3) .. image-sg:: /examples/images/sphx_glr_network_gridder_003.png :alt: network gridder :srcset: /examples/images/sphx_glr_network_gridder_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 181-184 The final step before we can grid the network is setting the data to edge centroids. We do this by averaging the data at the nodes that are connected to the edges. This is done by using the edge_node_connectivity of the network. .. GENERATED FROM PYTHON SOURCE LINES 185-196 .. code-block:: Python edge_data = xr.DataArray( data=uda_1d_interpolated.data[refined_network.edge_node_connectivity].mean(axis=1), dims=(refined_network.edge_dimension,), ) uda_1d_edge = xu.UgridDataArray(edge_data, grid=refined_network) fig, ax = plt.subplots() uda_1d_edge.ugrid.plot(ax=ax, zorder=10) ugrid2d.plot(ax=ax, color="gray", alpha=0.5, zorder=3) .. image-sg:: /examples/images/sphx_glr_network_gridder_004.png :alt: network gridder :srcset: /examples/images/sphx_glr_network_gridder_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 197-204 Gridding -------- Finally, we can grid the data to the 2D grid. We can do this by using the :class:`xugrid.regrid.gridder.NetworkGridder` class. This class takes the Ugrid1d grid as source and Ugrid2d grit as target, the method to use for gridding and the data to grid. .. GENERATED FROM PYTHON SOURCE LINES 205-216 .. code-block:: Python from xugrid.regrid.gridder import NetworkGridder gridder = NetworkGridder( source=uda_1d_edge.ugrid.grid, target=ugrid2d, method="mean", ) gridder .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 217-219 Next, we can grid the data. Call the :meth:`xugrid.regrid.gridder.NetworkGridder.regrid` method to grid the data. .. GENERATED FROM PYTHON SOURCE LINES 220-228 .. code-block:: Python network_gridded = gridder.regrid(uda_1d_edge) fig, ax = plt.subplots() network_gridded.ugrid.plot(ax=ax) uda_1d_edge.ugrid.grid.plot(ax=ax, color="black", alpha=0.5, zorder=2) ugrid2d.plot(ax=ax, color="gray", alpha=0.5, zorder=3) .. image-sg:: /examples/images/sphx_glr_network_gridder_005.png :alt: network gridder :srcset: /examples/images/sphx_glr_network_gridder_005.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.334 seconds) .. _sphx_glr_download_examples_network_gridder.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: network_gridder.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: network_gridder.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: network_gridder.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_