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

Dual Mesh Construction #859

Open
wants to merge 78 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
5a4e46d
Added dual mesh initial support
aaronzedwick Jul 17, 2024
058662b
Updated Mesh Construction Method
aaronzedwick Jul 19, 2024
c2d2ab7
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Jul 19, 2024
5890270
Removed Old Files
aaronzedwick Jul 19, 2024
96a61b8
Merge branch 'zedwick/dual_mesh' of https://github.com/UXARRAY/uxarra…
aaronzedwick Jul 19, 2024
6b2468b
Updated API added comprehensive test
aaronzedwick Jul 22, 2024
5d1f918
Fixed pre-commit
aaronzedwick Jul 22, 2024
cd2f643
Merge branch 'main' into zedwick/dual_mesh
philipc2 Jul 23, 2024
8d61fe9
optimize code
philipc2 Jul 24, 2024
39a0902
update dual mesh construction and duplicate node validation
philipc2 Jul 25, 2024
09efe64
progress on migrating implementation to Grid
philipc2 Jul 25, 2024
fe221f7
Testing Notebook
aaronzedwick Jul 26, 2024
eea2157
Update Untitled.ipynb
aaronzedwick Jul 26, 2024
39d43b1
Updated Notebook
aaronzedwick Jul 26, 2024
366a5f7
Update dual-mesh.ipynb
aaronzedwick Jul 26, 2024
098ef2b
Update Notebook
aaronzedwick Jul 26, 2024
f223941
Update docs
aaronzedwick Jul 26, 2024
75b6f65
Update dual-mesh.ipynb
aaronzedwick Jul 26, 2024
b628c8e
Merge branch 'main' into zedwick/dual_mesh
philipc2 Jul 29, 2024
1dffe37
Updated Merge Duplicate Nodes and cleaned up code
aaronzedwick Jul 29, 2024
62291c5
Added Duplicate Nodes Test
aaronzedwick Aug 2, 2024
24a7ece
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Aug 2, 2024
914db53
Duplicate nodes error, updated index, fix codecov,
aaronzedwick Aug 2, 2024
b01756a
Merge branch 'zedwick/dual_mesh' of https://github.com/UXARRAY/uxarra…
aaronzedwick Aug 2, 2024
2494008
Fixed pre-commit
aaronzedwick Aug 2, 2024
7c91d52
fixed duplicate check
aaronzedwick Aug 2, 2024
9d880f9
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Aug 6, 2024
abf7556
Moved to dual.py remove duplication merge
aaronzedwick Aug 6, 2024
fe909af
Updated API and Benchmarks
aaronzedwick Aug 6, 2024
dbb935c
Updated face construction and ordering
aaronzedwick Aug 6, 2024
314e877
Optimization and clean up
aaronzedwick Aug 6, 2024
558f871
Update dual-mesh.ipynb
aaronzedwick Aug 7, 2024
0b22e4f
Updated userguide.rst
aaronzedwick Aug 7, 2024
5dd4f81
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Aug 9, 2024
dd354e3
Fixed pre-commit
aaronzedwick Aug 9, 2024
7cbecdf
Update docs/userguide.rst
aaronzedwick Aug 12, 2024
c87554b
Added docstrings
aaronzedwick Aug 16, 2024
7f8c50e
Update dual.py
aaronzedwick Aug 16, 2024
692cb03
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Aug 16, 2024
8778b80
Merge branch 'main' into zedwick/dual_mesh
philipc2 Aug 16, 2024
cbfdb74
Added dual mesh support of DataArrays
aaronzedwick Aug 20, 2024
7a02c55
Fixed asv config file
aaronzedwick Aug 20, 2024
65c7b5a
Added name to data array
aaronzedwick Aug 21, 2024
e3bdd6a
Fixed constructed node face connectivity error
aaronzedwick Aug 21, 2024
374770e
Updated user guide
aaronzedwick Aug 22, 2024
acc4a42
Fixed docs
aaronzedwick Aug 22, 2024
a73a2de
Removed method parameter
aaronzedwick Sep 3, 2024
68a082d
Added support for UxDatasets
aaronzedwick Sep 4, 2024
9219579
Update dual user guide
aaronzedwick Sep 4, 2024
9657d8e
Update index.rst
aaronzedwick Sep 4, 2024
4e039bc
Updated Test Cases
aaronzedwick Sep 4, 2024
c0feb34
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Sep 4, 2024
cda5e96
Update test_grid.py
aaronzedwick Sep 4, 2024
0667e0d
Merge branch 'zedwick/dual_mesh' of https://github.com/UXARRAY/uxarra…
aaronzedwick Sep 4, 2024
f690a3e
Updated colormaps
aaronzedwick Sep 4, 2024
25ee56e
pre-commit fix
aaronzedwick Sep 4, 2024
bdadd23
Notebook Update
aaronzedwick Sep 5, 2024
4ff128d
Update dual-mesh.ipynb
aaronzedwick Sep 5, 2024
c1bd224
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Sep 10, 2024
2db6390
Update dual-mesh.ipynb
aaronzedwick Sep 10, 2024
e1d9621
Fixed Dimension Bug
aaronzedwick Sep 10, 2024
a870c20
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Sep 10, 2024
eeb6c62
Fixed pre-commit
aaronzedwick Sep 10, 2024
7ab0cdb
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Sep 17, 2024
03bc8b7
Update mpas_ocean.py
aaronzedwick Sep 17, 2024
3e0a197
Added warnings
aaronzedwick Sep 17, 2024
8c44fb0
Fixed test failures
aaronzedwick Sep 17, 2024
bc88eaf
Merge branch 'main' into zedwick/dual_mesh
philipc2 Sep 17, 2024
6612f56
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Sep 17, 2024
e827b52
Updated notebook and jit
aaronzedwick Sep 19, 2024
af98a0a
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Sep 24, 2024
149aaa5
Merge branch 'zedwick/dual_mesh' of https://github.com/UXARRAY/uxarra…
aaronzedwick Sep 24, 2024
b8750fc
Merge pre-commit fix
aaronzedwick Sep 24, 2024
4931f3f
Merge branch 'main' into zedwick/dual_mesh
aaronzedwick Sep 27, 2024
6f6d981
Merge branch 'main' into zedwick/dual_mesh
philipc2 Sep 27, 2024
853ece5
Merge branch 'main' into zedwick/dual_mesh
rajeeja Oct 1, 2024
d7b09f2
Updated notebook
aaronzedwick Oct 2, 2024
5ab7b10
Update Dual Notebook
aaronzedwick Oct 2, 2024
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
16 changes: 15 additions & 1 deletion benchmarks/mpas_ocean.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,17 @@ def time_dataarray_to_polycollection(self, resolution, periodic_elements):
self.uxds[data_var].to_polycollection()


class ConstructTreeStructures(DatasetBenchmark):
class ConstructTreeStructures:

param_names = ['resolution']
params = ['480km', '120km']

def setup(self, resolution):
self.uxds = ux.open_dataset(file_path_dict[resolution][0], file_path_dict[resolution][1])

def teardown(self, resolution):
del self.uxds

def time_kd_tree(self, resolution):
self.uxds.uxgrid.get_kd_tree()

Expand Down Expand Up @@ -144,6 +154,10 @@ class HoleEdgeIndices(DatasetBenchmark):
def time_construct_hole_edge_indices(self, resolution):
ux.grid.geometry._construct_hole_edge_indices(self.uxds.uxgrid.edge_face_connectivity)

class DualMesh(DatasetBenchmark):
def time_dual_mesh_construction(self, resolution):
self.uxds.uxgrid.get_dual()

class CheckNorm:
param_names = ['resolution']
params = ['480km', '120km']
Expand Down
3 changes: 3 additions & 0 deletions docs/internal_api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ Validation
grid.validation._check_connectivity
grid.validation._check_duplicate_nodes
grid.validation._check_area
grid.validation._check_duplicate_nodes_indices
grid.validation._find_duplicate_nodes


Accurate Computing Utils
------------------------
Expand Down
355 changes: 355 additions & 0 deletions docs/user-guide/dual-mesh.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
{
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

@philipc2 philipc2 Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using UXarray we can construct the dual mesh using grid.compute_dual() , which returns a new grid object.


Reply via ReviewNB

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want me to replace everything with just this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, meant only the final portion.

aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

@philipc2 philipc2 Sep 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.relabel() doesn't seem to work when combining plots of lines. It works in your notebook because everything you combined are points. Do you know how to make it work for actual grid plots? @philipc2

aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
aaronzedwick marked this conversation as resolved.
Show resolved Hide resolved
"cells": [
{
"cell_type": "markdown",
"id": "0660f9ec-8fa3-44a7-b362-3aa6526d8550",
"metadata": {},
"source": [
"# Dual Grid Construction"
]
},
{
"cell_type": "markdown",
"id": "974ebf95-c0b1-4397-be4d-bd5cf42cc8bc",
"metadata": {},
"source": [
"A dual grid is a secondary grid built from a grid, by constructing new faces over the original grids nodes. One property of this means that if you take the dual grid of a dual grid, the orignal grid will be constructed. However, this will only work properly if the grid is not partial. UXarray allows the constructing of this dual grid on all three of our data structures using the following methods:\n",
"\n",
"* `Grid.get_dual()`\n",
"* `UxDataArray.get_dual()`\n",
"* `UxDataset.get_dual()`"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4fd7d3b3-5186-4157-841e-1b4c9f38bb62",
"metadata": {},
"outputs": [],
"source": [
"import uxarray as ux\n",
"import warnings\n",
"\n",
"warnings.filterwarnings(\"ignore\")\n",
"\n",
"plot_kwargs = {\n",
" \"backend\": \"matplotlib\",\n",
" \"aspect\": 2,\n",
" \"fig_size\": 400,\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1eebd05d-506e-4227-aa8e-f1212aae30f2",
"metadata": {},
"outputs": [],
"source": [
"file = \"../../test/meshfiles/mpas/QU/mesh.QU.1920km.151026.nc\"\n",
"\n",
"uxds = ux.open_dataset(file, file)"
]
},
{
"cell_type": "markdown",
"id": "1e6ddbd8-7034-4ddd-bdd0-4454d76ea390",
"metadata": {},
"source": [
"## Computing the Dual Grid"
]
},
{
"cell_type": "markdown",
"id": "dc3b2464-b824-413f-b2e6-40b1e7049f3b",
"metadata": {},
"source": [
"When computing the dual of a grid, the original grid is typically referred to as the \"Primal\" grid. The corner nodes of the Primal grid become the face centers of the Dual grid, and the face centers of the Primal grid become the corner nodes of the Dual grid. This means that variables that were originally face-centered on the Primal grid will be node-centered on the Dual grid, and vice versa. Using UXarray we can construct the dual mesh using `grid.compute_dual()`, which returns a new `Grid` object."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6486e0e4-1908-4363-8196-2efa9e521e56",
"metadata": {},
"outputs": [],
"source": [
"grid = uxds.uxgrid"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "925a82d6-2947-4b15-a3ff-0b0612bc5ba0",
"metadata": {},
"outputs": [],
"source": [
"dual = grid.get_dual()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "27fd5578-996e-4cdf-be90-0f50cf322684",
"metadata": {},
"outputs": [],
"source": [
"(\n",
" grid.plot(title=\"Primal\", backend=\"matplotlib\", aspect=2)\n",
" + dual.plot(title=\"Constructed Dual\", backend=\"matplotlib\", aspect=2)\n",
").opts(fig_size=350).cols(1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e8bf665c-6465-473b-91f5-af180d0de7e1",
"metadata": {},
"outputs": [],
"source": [
"(\n",
" grid.plot(title=\"Red=Grid\\nBlue=Dual\", backend=\"bokeh\", color=\"red\")\n",
" * dual.plot(backend=\"bokeh\", color=\"blue\")\n",
" * grid.plot.face_centers(backend=\"bokeh\", size=5, color=\"black\")\n",
")"
]
},
{
"cell_type": "markdown",
"id": "721498b4-d587-4e4e-b1dc-6d8948a7f3f6",
"metadata": {},
"source": [
"## Computing the Dual Grid with Data"
]
},
{
"cell_type": "markdown",
"id": "9640cb00-6896-49de-b607-1721a8462d53",
"metadata": {},
"source": [
"We can also take a dual mesh of a `UxDataArray`. The concept for constructing the `Grid` remains the same, and what is constructed will be identical. The difference is the data stored inside the `UxDataArray` will be transfered with the dual mesh. The key differences is the location that the data is stored. The data transfer process works as follows:\n",
"\n",
"* Face centered data becomes node centered, as each face becomes a node in the dual mesh.\n",
"* Node centered data becomes face centered, as each node becomes a face in the dual mesh.\n",
"* Edge centered data remains unchanged, as the edge centers will remain in the same place, despite the edges themselves being different."
]
},
{
"cell_type": "markdown",
"id": "c55b2285-046d-460c-8e64-1bb204a36177",
"metadata": {},
"source": [
"### Face Centered Data"
]
},
{
"cell_type": "markdown",
"id": "ebdbc2da-938b-455a-9c84-090faf0e25f9",
"metadata": {},
"source": [
"When constructing the dual mesh paired with a face centered variable, the data becomes node centered. We can then plot this using `topological_mean` to get the dual data to the faces for proper visualization comparisions."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "75e86af7-de9c-4013-91f6-9fd9e9c0c3ad",
"metadata": {},
"outputs": [],
"source": [
"uxds_dual_face = uxds[\"latCell\"].get_dual()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8bbcd1ad-d719-409a-b7f0-a1ad6ec43b78",
"metadata": {},
"outputs": [],
"source": [
"(\n",
" uxds[\"latCell\"].plot.rasterize(\n",
" backend=\"matplotlib\",\n",
" title=\"Face centered data on Primal Mesh\",\n",
" cmap=ux.cmaps.sequential_green_blue,\n",
" )\n",
" + uxds_dual_face.topological_mean(destination=\"face\").plot.rasterize(\n",
" backend=\"matplotlib\",\n",
" title=\"Node Centered Data on Dual Mesh\",\n",
" cmap=ux.cmaps.sequential_green_blue,\n",
" )\n",
").opts(fig_size=350).cols(1)"
]
},
{
"cell_type": "markdown",
"id": "62d27519-aced-47b0-841e-447bf3a200c2",
"metadata": {},
"source": [
"### Node Centered Data"
]
},
{
"cell_type": "markdown",
"id": "6819dd2b-91a1-465f-8e2e-11cf14b81a7e",
"metadata": {},
"source": [
"When constructing the dual mesh paired with a node centered variable, the data becomes face centered. A benefit of computing the dual of a node centered variable is that it allows us to visualize the data as polygons."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c68473ae-dac6-422e-b322-71cfbfe3f876",
"metadata": {},
"outputs": [],
"source": [
"uxds_dual_node = uxds[\"xVertex\"].get_dual()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fd4847a0-65e5-4973-9269-47e49edb7911",
"metadata": {},
"outputs": [],
"source": [
"(\n",
" uxds[\"xVertex\"]\n",
" .topological_mean(destination=\"face\")\n",
" .plot.rasterize(\n",
" backend=\"matplotlib\",\n",
" title=\"Node centered data on Primal Mesh\",\n",
" cmap=ux.cmaps.sequential_green_blue,\n",
" )\n",
" + uxds_dual_node.plot.rasterize(\n",
" backend=\"matplotlib\",\n",
" title=\"Face Centered Data on Dual Mesh\",\n",
" cmap=ux.cmaps.sequential_green_blue,\n",
" )\n",
").opts(fig_size=350).cols(1)"
]
},
{
"cell_type": "markdown",
"id": "99ab5fd9-76ea-4b11-91ee-95bf535e3e7f",
"metadata": {},
"source": [
"### Edge Centered Data"
]
},
{
"cell_type": "markdown",
"id": "4a4b8f5a-4158-4f45-b7a7-9e82fcdac353",
"metadata": {},
"source": [
"When constructing the dual mesh paired with an edge centered variable, the data will stay edge centered. However, a plotting example cannot be shown, as the `topological_mean` needed to visualize edge centered data is not currently implemented for edge centered data."
]
},
{
"cell_type": "markdown",
"id": "1dafeee0-3d1d-49dd-aa41-8222463ee3b3",
"metadata": {},
"source": [
"### UxDataset"
]
},
{
"cell_type": "markdown",
"id": "36df7eac-d50d-4bae-883c-310529a1a5f0",
"metadata": {},
"source": [
"We can also construct a dual mesh from an entire dataset, which will convert the whole `UxDataset` to its dual mesh form. Below we can see the dataset before the dual mesh is constructed."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "97a884d0-5966-4bfc-b505-ceb3c37c4b47",
"metadata": {},
"outputs": [],
"source": [
"uxds"
]
},
{
"cell_type": "markdown",
"id": "c65085a8-4111-4019-860c-dd28a7f3aefc",
"metadata": {},
"source": [
"Now we can construct the dual and see the new dataset that is returned."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9c14a1bd-d06a-4ccb-92a5-9054e063e740",
"metadata": {},
"outputs": [],
"source": [
"uxds_dual = uxds.get_dual()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7c039b32-03cd-4b83-b41e-dc5e06d118a0",
"metadata": {},
"outputs": [],
"source": [
"uxds_dual"
]
},
{
"cell_type": "markdown",
"id": "fcac470d-4025-4fe8-afde-4a7bdf05c3ec",
"metadata": {},
"source": [
"As you can see, transforms the whole dataset. We can now take any variable and plot it, as shown below."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "85dedc57-f179-43b9-a55c-c0b469330988",
"metadata": {},
"outputs": [],
"source": [
"uxds_dual[\"xVertex\"].plot.rasterize(\n",
" backend=\"matplotlib\",\n",
" title=\"xVertex from UxDataset dual mesh\",\n",
" cmap=ux.cmaps.sequential_green_blue,\n",
").opts(fig_size=350)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4a6450bd-e6aa-4cca-bac8-0c673ac84349",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading
Loading