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

Non-Conservative Zonal Mean #785

Closed
wants to merge 115 commits into from
Closed
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
6c9f2bc
set up boiler plate
philipc2 May 10, 2024
786f221
update zonal mean boilerplate
philipc2 May 13, 2024
0627541
Merge branch 'main' into zonal-mean
philipc2 May 13, 2024
fb1e82f
Merge branch 'main' into zonal-mean
philipc2 May 14, 2024
73a05d2
Add functions implementation description
hongyuchen1030 May 14, 2024
8b3aefb
update string
hongyuchen1030 May 15, 2024
1c9711f
Merge branch 'main' into zonal-mean
philipc2 May 15, 2024
bfdf8f7
Merge branch 'main' into zonal-mean
philipc2 May 16, 2024
c43489e
add boilerplate for user guide section
philipc2 May 16, 2024
b10787b
implement _get_candidate_faces_at_constant_latitude
amberchen122 May 17, 2024
c9e02eb
Merge branch 'main' into zonal-mean
philipc2 May 17, 2024
8fc9f51
change input to zonal.py in api
amberchen122 May 20, 2024
3982151
Merge branch 'main' into zonal-mean
philipc2 May 20, 2024
40c878e
Optimizing _get_cartesian_face_edge_nodes
hongyuchen1030 May 20, 2024
efe2ead
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 May 20, 2024
55ab278
debug for _get_cartesian_single_face_edge_nodes
hongyuchen1030 May 20, 2024
89761f4
update the `_get_cartesian_face_edge_nodes`
hongyuchen1030 May 20, 2024
eddbc95
initial commit
hongyuchen1030 May 20, 2024
386e92d
Finished implementation
hongyuchen1030 May 20, 2024
c1418ee
Fixed faces with holes
hongyuchen1030 May 20, 2024
98044b3
Fix precommit
hongyuchen1030 May 20, 2024
365009f
Merge branch 'Optimized-`get_cartesian_face_edge_nodes`and`get_lonlat…
hongyuchen1030 May 20, 2024
d672ef2
finished zonal_mean implimentation using the new _get_cartesian_face_…
amberchen122 May 21, 2024
dd95be2
set dimension of returning uxda
amberchen122 May 21, 2024
40bab03
Merge branch 'main' into zonal-mean
philipc2 May 21, 2024
3319f1c
handle zero candidate faces case
amberchen122 May 21, 2024
417f2c3
initial commit for test_zonal
amberchen122 May 21, 2024
2839310
Merge branch 'main' into zonal-mean
philipc2 Jun 4, 2024
afd2909
placeholder
amberchen122 Jun 11, 2024
f52b3c6
user defined latitude range
amberchen122 Jun 18, 2024
e2d291f
update api
amberchen122 Jun 18, 2024
7eb648b
user guide
amberchen122 Jun 18, 2024
bc4544c
zonal unit test mocking _get_zonal_faces_weight_at_constLat
amberchen122 Jun 18, 2024
7f05938
correct internal api directory
amberchen122 Jun 18, 2024
662f873
update interface
amberchen122 Jun 18, 2024
b7f7ab0
Merge branch 'main' into zonal-mean
philipc2 Jun 18, 2024
7eadff8
update `_get_cartesian_face_edge_nodes` calls
amberchen122 Jun 19, 2024
f2ff2b7
Revert "update `_get_cartesian_face_edge_nodes` calls"
amberchen122 Jun 19, 2024
4d2c8de
Merge branch 'main' into zonal-mean
hongyuchen1030 Jun 23, 2024
a2b5df2
update zonal desc
amberchen122 Jul 9, 2024
904fd4c
Merge remote-tracking branch 'origin/main' into zonal-mean
amberchen122 Jul 9, 2024
0a93fdd
change interface to include single lat
amberchen122 Jul 16, 2024
24db7df
Add Fill value testcase
hongyuchen1030 Jul 16, 2024
8f2175e
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Jul 16, 2024
e4ab62d
file test case
amberchen122 Jul 16, 2024
5423283
Merge remote-tracking branch 'upstream/zonal-mean' into zonal-mean
hongyuchen1030 Jul 16, 2024
47c5a8f
Add file testcase
hongyuchen1030 Jul 16, 2024
cf4fb1b
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 16, 2024
d983429
debug
hongyuchen1030 Jul 16, 2024
de2bf23
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Jul 16, 2024
c6707e4
Fix the zonal_mean bug
hongyuchen1030 Jul 16, 2024
4111e01
update user guide+latitude coordinate
amberchen122 Jul 17, 2024
f7c4dbe
file test
amberchen122 Jul 17, 2024
d59c520
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 18, 2024
e6c5f97
Force commit of ignored .nc files
amberchen122 Jul 19, 2024
e45cd3c
file values test
amberchen122 Jul 19, 2024
e85c7a3
initial fix for the i`is_ppole_point_inside`
hongyuchen1030 Jul 19, 2024
efa0317
Fix the face_weight calculation at the pole
hongyuchen1030 Jul 19, 2024
202b622
fix duplicate intersection point
hongyuchen1030 Jul 21, 2024
ebac890
fix no converge intersection point
hongyuchen1030 Jul 21, 2024
8515ddb
everthing pass for file `outCSne3`
hongyuchen1030 Jul 21, 2024
8dc2b9f
clean up
hongyuchen1030 Jul 21, 2024
0cc6750
add pole point testcase
hongyuchen1030 Jul 21, 2024
e402695
add raise runtime error for query near pole
amberchen122 Jul 21, 2024
99a6a73
add away from pole points test case
hongyuchen1030 Jul 21, 2024
ab605b1
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Jul 21, 2024
0ce60d8
Add pole point test case
hongyuchen1030 Jul 22, 2024
3064a34
typofix
hongyuchen1030 Jul 22, 2024
f73f53f
add equator
hongyuchen1030 Jul 22, 2024
6337ac4
add warning user
hongyuchen1030 Jul 22, 2024
342f94b
fix pole location logic
amberchen122 Jul 22, 2024
c794400
clean up
amberchen122 Jul 22, 2024
4fdc9aa
typo
amberchen122 Jul 22, 2024
6da3bea
update userguide.rst
amberchen122 Jul 22, 2024
11bf855
clean up
amberchen122 Jul 22, 2024
07aeffc
consistant naming for constLat
amberchen122 Jul 22, 2024
cbf9490
todo: right ground truth
amberchen122 Jul 22, 2024
266b71b
correct ground truth
amberchen122 Jul 22, 2024
00a4988
fix `pt_within_gca`
hongyuchen1030 Jul 22, 2024
bb70917
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 25, 2024
9f0db6e
orgnize test files into new folder
amberchen122 Jul 26, 2024
b423fe3
remove test files
amberchen122 Jul 26, 2024
e6811bc
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 28, 2024
154d2e0
update test_api
amberchen122 Jul 30, 2024
9a5d6e7
separate constants
amberchen122 Jul 30, 2024
d8e28a1
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 31, 2024
7d3010e
fix `_is_pole_inside`
hongyuchen1030 Aug 4, 2024
67ec68c
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Aug 4, 2024
617ffc7
Merge branch 'main' into zonal-mean
hongyuchen1030 Aug 4, 2024
4d42882
remove invalid testcase
hongyuchen1030 Aug 4, 2024
1ce4acc
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Aug 4, 2024
859bbde
zonal average across multiple dimensions, update user guide
philipc2 Aug 5, 2024
805160b
add new data variable to showcase zonal average
philipc2 Aug 5, 2024
2f0e3c2
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
philipc2 Aug 5, 2024
6f82887
add benchmark for zonal mean
philipc2 Aug 5, 2024
e85bcba
add zonal average user guide to index
philipc2 Aug 5, 2024
0847a1f
Merge branch 'main' into zonal-mean
philipc2 Aug 5, 2024
bd905db
Merge branch 'main' of https://github.com/UXARRAY/uxarray into zonal-…
amberchen122 Sep 17, 2024
f1a51c1
fix typo
amberchen122 Sep 17, 2024
d51b843
Merge branch 'main' into zonal-mean
philipc2 Sep 18, 2024
9b37229
Update test_integrate.py
amberchen122 Sep 18, 2024
f012bc0
workaround the precision issues again
hongyuchen1030 Sep 18, 2024
9a67080
fix precommit
amberchen122 Sep 18, 2024
f4385b1
add option to disable fma
philipc2 Sep 18, 2024
cd0a29c
update benchmarks
philipc2 Sep 18, 2024
8a704c5
Merge branch 'main' into zonal-mean
philipc2 Sep 18, 2024
861c8f7
update ZonalMean benchmarks
philipc2 Sep 18, 2024
064a465
use numba isclose
philipc2 Sep 18, 2024
b6be73d
use numba cross and dot in newton solver
philipc2 Sep 18, 2024
837542e
Merge branch 'main' into zonal-mean
hongyuchen1030 Sep 18, 2024
aaa7c7a
Merge branch 'main' into zonal-mean
philipc2 Sep 24, 2024
4e647b2
Merge branch 'main' into zonal-mean
philipc2 Oct 4, 2024
869b17e
remove test file
amberchen122 Oct 14, 2024
d00a971
update zonal_mean signiture to explicitly accept two types
amberchen122 Oct 14, 2024
c307959
correct var name
amberchen122 Oct 14, 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
131 changes: 131 additions & 0 deletions docs/user-guide/zonal-mean.ipynb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/userguide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ common tasks that you can accomplish with UXarray.
user-guide/grid-formats.rst
user-guide/data-structures.ipynb
user-guide/area_calc.ipynb
user-guide/zonal-mean.ipynb
424 changes: 393 additions & 31 deletions test/test_geometry.py

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions test/test_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,7 @@ def test_from_face_vertices(self):


class TestLatlonBounds(TestCase):
gridfile_mpas = current_path / "meshfiles" / "mpas" / "QU" / "oQU480.231010.nc"
def test_populate_bounds_GCA_mix(self):
face_1 = [[10.0, 60.0], [10.0, 10.0], [50.0, 10.0], [50.0, 60.0]]
face_2 = [[350, 60.0], [350, 10.0], [50.0, 10.0], [50.0, 60.0]]
Expand All @@ -932,3 +933,9 @@ def test_populate_bounds_GCA_mix(self):
bounds_xarray = grid.bounds
face_bounds = bounds_xarray.values
nt.assert_allclose(grid.bounds.values, expected_bounds, atol=ERROR_TOLERANCE)

def test_populate_bounds_MPAS(self):
xrds = xr.open_dataset(self.gridfile_mpas)
uxgrid = ux.Grid.from_dataset(xrds, use_dual=True)
bounds_xarray = uxgrid.bounds
pass
46 changes: 7 additions & 39 deletions test/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,34 +241,6 @@ def test_angle_of_2_vectors(self):

class TestFaceEdgeConnectivityHelper(TestCase):

def test_get_cartesian_face_edge_nodes(self):
# Load the dataset

uxds = ux.open_dataset(gridfile_geoflowsmall_grid,
gridfile_geoflowsmall_var)

# Initialize array

face_edges_connectivity_cartesian = []

# Get the connectivity

for i in range(len(uxds.uxgrid.face_node_connectivity)):
face_edges_connectivity_cartesian.append(
_get_cartesian_face_edge_nodes(
uxds.uxgrid.face_node_connectivity.values[i],
uxds.uxgrid.face_edge_connectivity.values[i],
uxds.uxgrid.edge_node_connectivity.values,
uxds.uxgrid.node_x.values, uxds.uxgrid.node_y.values,
uxds.uxgrid.node_z.values))

# Stack the arrays to get the desired (3,3) array

face_edges_connectivity_cartesian = np.vstack(
face_edges_connectivity_cartesian)

assert (face_edges_connectivity_cartesian.ndim == 3)

def test_get_cartesian_face_edge_nodes_pipeline(self):
# Create the vertices for the grid, based around the North Pole

Expand All @@ -281,14 +253,13 @@ def test_get_cartesian_face_edge_nodes_pipeline(self):
# Construct the grid from the vertices
grid = ux.Grid.from_face_vertices(vertices, latlon=False)
face_edges_connectivity_cartesian = _get_cartesian_face_edge_nodes(
grid.face_node_connectivity.values[0],
grid.face_edge_connectivity.values[0],
grid.edge_node_connectivity.values, grid.node_x.values,
grid.face_node_connectivity.values,
grid.node_x.values,
grid.node_y.values, grid.node_z.values)

# Check that the face_edges_connectivity_cartesian works as an input to _pole_point_inside_polygon
result = ux.grid.geometry._pole_point_inside_polygon(
'North', face_edges_connectivity_cartesian)
'North', face_edges_connectivity_cartesian[0])

# Assert that the result is True

Expand All @@ -307,14 +278,12 @@ def test_get_cartesian_face_edge_nodes_filled_value(self):
# Construct the grid from the vertices
grid = ux.Grid.from_face_vertices(vertices, latlon=False)
face_edges_connectivity_cartesian = _get_cartesian_face_edge_nodes(
grid.face_node_connectivity.values[0],
grid.face_edge_connectivity.values[0],
grid.edge_node_connectivity.values, grid.node_x.values,
grid.face_node_connectivity.values, grid.node_x.values,
grid.node_y.values, grid.node_z.values)

# Check that the face_edges_connectivity_cartesian works as an input to _pole_point_inside_polygon
result = ux.grid.geometry._pole_point_inside_polygon(
'North', face_edges_connectivity_cartesian)
'North', face_edges_connectivity_cartesian[0])

# Assert that the result is True
self.assertTrue(result)
Expand All @@ -331,10 +300,9 @@ def test_get_lonlat_face_edge_nodes_pipeline(self):
# Construct the grid from the vertices
grid = ux.Grid.from_face_vertices(vertices, latlon=False)
face_edges_connectivity_lonlat = _get_lonlat_rad_face_edge_nodes(
grid.face_node_connectivity.values[0],
grid.face_edge_connectivity.values[0],
grid.edge_node_connectivity.values, grid.node_lon.values,
grid.face_node_connectivity.values,grid.node_lon.values,
grid.node_lat.values)
face_edges_connectivity_lonlat = face_edges_connectivity_lonlat[0]

# Convert all the values into cartesian coordinates
face_edges_connectivity_cartesian = []
Expand Down
Empty file added test/test_zonal.py
Empty file.
66 changes: 65 additions & 1 deletion uxarray/core/dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from uxarray.grid import Grid
import uxarray.core.dataset
from uxarray.grid.utils import _get_cartesian_face_edge_nodes

if TYPE_CHECKING:
from uxarray.core.dataset import UxDataset
Expand All @@ -21,6 +22,10 @@
_calculate_edge_node_difference,
)

from uxarray.core.zonal import (
_non_conservative_zonal_mean_constant_latitudes,
)

from uxarray.plot.accessor import UxDataArrayPlotAccessor
from uxarray.subset import DataArraySubsetAccessor
from uxarray.remap import UxDataArrayRemapAccessor
Expand Down Expand Up @@ -576,7 +581,66 @@ def difference(self, destination: Optional[str] = "edge"):

return uxda

pass
def zonal_mean(self, step_size=1):
amberchen122 marked this conversation as resolved.
Show resolved Hide resolved
"""Computes the Zonal Mean for face-centered data. The zonal average is
computed from -90 to 90 degrees latitude, with a given step size.

Parameters
----------
step_size : float, default=1
The step size for the zonal average.

Returns
-------
UxDataArray
UxDataArray containing the zonal average of the data variable

Example
-------
>>> uxds['var'].zonal_mean()
"""

# Check if the data is face-centered
if not self._face_centered():
raise NotImplementedError(
"Zonal average computations are currently only supported for face-centered data variables."
)

# Get the data, face bounds, face node connectivity, and whether the faces are latlon
data = self.values
face_bounds = self.uxgrid.bounds.values
is_latlonface = False # Currently not used, but may be useful in the future

# Get the list of face polygon represented by edges in Cartesian coordinates
face_edges_cart = _get_cartesian_face_edge_nodes(
self.uxgrid.face_node_connectivity.values,
self.uxgrid.node_x.values,
self.uxgrid.node_y.values,
self.uxgrid.node_z.values,
)

_zonal_avg_res = _non_conservative_zonal_mean_constant_latitudes(
face_edges_cart,
face_bounds,
data,
step_size,
is_latlonface=is_latlonface,
)

# Set Dimension of result
dims = list(self.dims[:-1]) + ["latitude"]

# Result is stored and returned as a UxDataArray
uxda = UxDataArray(
_zonal_avg_res,
uxgrid=self.uxgrid,
dims=dims,
name=self.name + "_zonal_average"
if self.name is not None
else "zonal_average",
)

return uxda

def _face_centered(self) -> bool:
"""Returns whether the data stored is Face Centered (i.e. contains the
Expand Down
157 changes: 157 additions & 0 deletions uxarray/core/zonal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import numpy as np
from uxarray.constants import INT_FILL_VALUE
from uxarray.grid.integrate import _get_zonal_faces_weight_at_constLat


def _get_candidate_faces_at_constant_latitude(bounds, constLat: float) -> np.ndarray:
"""Return the indices of the faces whose latitude bounds contain the
constant latitude.

Parameters
----------
bounds : np.ndarray, shape (n_face, 2, 2)
The latitude and longitude bounds of the faces.

constLat : float
The constant latitude to check against. Expected range is [-90, 90].

Returns
-------
np.ndarray, shape (n_candidate_faces, )
An array of indices of the faces whose latitude bounds contain the constant latitude `constLat`.
"""

# Check if the constant latitude is within the range of [-90, 90]
if constLat < -90 or constLat > 90:
raise ValueError("The constant latitude must be within the range of [-90, 90].")

# Extract the latitude bounds
lat_bounds_min = bounds[:, 0, 0] # Minimum latitude bound
lat_bounds_max = bounds[:, 0, 1] # Maximum latitude bound

# Check if the constant latitude is within the bounds of each face
within_bounds = (lat_bounds_min <= constLat) & (lat_bounds_max >= constLat)

# Get the indices of faces where the condition is True
candidate_faces = np.where(within_bounds)[0]

return candidate_faces


def _non_conservative_zonal_mean_constant_one_latitude(
face_edges_cart: np.ndarray,
face_bounds: np.ndarray,
face_data: np.ndarray,
constLat: float,
is_latlonface=False,
) -> float:
"""Helper function for _non_conservative_zonal_mean_constant_latitudes.
Calculate the zonal mean of the data at a constant latitude.

Parameters
----------
face_edges_cart : np.ndarray, shape (n_face, n_edge, 2, 3)
The Cartesian coordinates of the face edges.
bounds : np.ndarray, shape (n_face, 2, 2)
The latitude and longitude bounds of the faces.
face_data : np.ndarray, shape (..., n_face)
The data on the faces.
constLat : float
The constant latitude in degrees. Expected range is [-90, 90].
is_latlonface : bool, optional
A flag indicating if the current face is a latitudinal/longitudinal (latlon) face,
meaning its edges align with lines of constant latitude or longitude. If `True`,
edges are treated as following constant latitudinal or longitudinal lines. If `False`,
edges are considered as great circle arcs (GCA). Default is `False`.

Returns
-------
float
The zonal mean of the data at the constant latitude.
"""

# Get the indices of the faces whose latitude bounds contain the constant latitude
candidate_faces_indices = _get_candidate_faces_at_constant_latitude(
face_bounds, constLat
)

# Check if there are no candidate faces,
if len(candidate_faces_indices) == 0:
return INT_FILL_VALUE # TODO: Determin an appropriate dummy value

# Get the face data of the candidate faces
candidate_face_data = face_data[..., candidate_faces_indices]

# Get the list of face polygon represented by edges in Cartesian coordinates
candidate_face_edges_cart = face_edges_cart[candidate_faces_indices]

weight_df = _get_zonal_faces_weight_at_constLat(
candidate_face_edges_cart,
np.sin(np.deg2rad(constLat)), # Latitude in cartesian coordinates
face_bounds,
is_directed=False,
is_latlonface=is_latlonface,
)

# Compute the zonal mean(weighted average) of the candidate faces
weights = weight_df["weight"].values
zonal_mean = np.sum(candidate_face_data * weights) / np.sum(weights)

return zonal_mean


def _non_conservative_zonal_mean_constant_latitudes(
face_edges_cart: np.ndarray,
face_bounds: np.ndarray,
face_data: np.ndarray,
step_size: float,
is_latlonface=False,
) -> np.ndarray:
"""Calculate the zonal mean of the data from -90 to 90 degrees latitude,
with a given step size.

Parameters
----------
face_edges_cart : np.ndarray, shape (n_face, n_edge, 2, 3)
The Cartesian coordinates of the face edges.
bounds : np.ndarray, shape (n_face, 2, 2)
The latitude and longitude bounds of the faces.
face_data : np.ndarray, shape (..., n_face)
The data on the faces. It may have multiple non-grid dimensions (e.g., time, level).
step_size : float
The step size in degrees for the latitude.
is_latlonface : bool, optional
A flag indicating if the current face is a latitudinal/longitudinal (latlon) face,
meaning its edges align with lines of constant latitude or longitude. If `True`,
edges are treated as following constant latitudinal or longitudinal lines. If `False`,
edges are considered as great circle arcs (GCA). Default is `False`.

Returns
-------
np.ndarray
The zonal mean of the data from -90 to 90 degrees latitude. The shape of the output
is (..., n_latitudes), where n_latitudes is the number of latitude steps from -90 to 90.
"""

# Generate latitudes from -90 to 90 with the given step size
latitudes = np.arange(-90, 90 + step_size, step_size)

# Initialize an empty list to store the zonal mean for each latitude
zonal_means = []

# Calculate the zonal mean for each latitude
for constLat in latitudes:
zonal_mean = _non_conservative_zonal_mean_constant_one_latitude(
face_edges_cart, face_bounds, face_data, constLat, is_latlonface
)
zonal_means.append(zonal_mean)

# Convert the list of zonal means to a NumPy array
zonal_means = np.array(zonal_means)

# Reshape the zonal mean array to have the same leading dimensions as the input data
# and an additional dimension for the latitudes
expected_shape = face_data.shape[:-1] + (len(latitudes),)
zonal_means = zonal_means.reshape(expected_shape)

return zonal_means
38 changes: 23 additions & 15 deletions uxarray/grid/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -881,23 +881,31 @@ def _populate_bounds(
intervals_tuple_list = []
intervals_name_list = []

faces_edges_cartesian = _get_cartesian_face_edge_nodes(
grid.face_node_connectivity.values,
grid.node_x.values,
grid.node_y.values,
grid.node_z.values,
)

faces_edges_lonlat_rad = _get_lonlat_rad_face_edge_nodes(
grid.face_node_connectivity.values,
grid.node_lon.values,
grid.node_lat.values,
)

for face_idx, face_nodes in enumerate(grid.face_node_connectivity):
face_edges_cartesian = _get_cartesian_face_edge_nodes(
grid.face_node_connectivity.values[face_idx],
grid.face_edge_connectivity.values[face_idx],
grid.edge_node_connectivity.values,
grid.node_x.values,
grid.node_y.values,
grid.node_z.values,
)
face_edges_cartesian = faces_edges_cartesian[face_idx]

face_edges_lonlat_rad = _get_lonlat_rad_face_edge_nodes(
grid.face_node_connectivity.values[face_idx],
grid.face_edge_connectivity.values[face_idx],
grid.edge_node_connectivity.values,
grid.node_lon.values,
grid.node_lat.values,
)
# Skip processing if the face is a dummy face
if np.any(face_edges_cartesian == INT_FILL_VALUE):
continue

face_edges_lonlat_rad = faces_edges_lonlat_rad[face_idx]

# Skip processing if the face is a dummy face
if np.any(face_edges_lonlat_rad == INT_FILL_VALUE):
continue

is_GCA_list = (
is_face_GCA_list[face_idx] if is_face_GCA_list is not None else None
Expand Down
Loading
Loading