Skip to content

Commit d9f091f

Browse files
rajeejaphilipc2aaronzedwick
authored
Area correction for when an edge is the line of constant latitude (#1120)
* o First draft area correction * o Add test and notebook to showcase area correction * o Add more to notebook, mathematical formulation of correction and plot of original triangle * o fix notebook * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * o Cleanup notebook * o Fix spaces * Use $ for formula in notebook, mathjax seems to be configured correctly * Attempted fix for notebook error * notebook fix * Changed markdown style of notebook * Update area_calc.ipynb * Update area_calc.ipynb * o Remove bad file * o checked in files my mistake * o Remove unnecessary files * o Complete TODO fix area correct sign based on edge lon and hemisphere. Add notebook example. TODO: Add test and corner cases * o Fix tests * o change grid coords to match new constants * o Correct math formula display for doc page html, use latex in notebook * Fix tests and notebook, add plot, cleanup code, getting ready to get out of draft mode * Remove all o/p from notebook * o Delete bad files * o Use new mathjax * o Fix tests and notebook, also use MathJAX3 and 2 is no longer supported * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * Update uxarray/grid/area.py Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> * o Add docstring for correct_area * o notebook clear output * o Add sep for _fesom, removes warnings, remove one more comment * o ruff fix * o Use new simple formatting for doc math formulae * o Add docstring for correct_area in grid.py * o Add another example for face area calculation that motivates the usage of correction for zonal averaging calculation etc. * o Remove hemisphere string and add check for skipping when lon_diff of edge is more than 180 deg * o extra normalization and simplify calc * o Use pythonic variable names for Gaussian and triangular quadrature points for area calc. * o Use latitude_adjusted_area as a flag to indicate area correction requirement when users wants to specify that all edges in a mesh that have the same latitude endpoints are lines of constant latitude, Add TODO for const lattitude edge flag and spherical changes --------- Co-authored-by: Philip Chmielowiec <67855069+philipc2@users.noreply.github.com> Co-authored-by: Aaron Zedwick <aazedwick@gmail.com> Co-authored-by: Aaron Zedwick <95507181+aaronzedwick@users.noreply.github.com>
1 parent 90e25ef commit d9f091f

7 files changed

Lines changed: 2313 additions & 270 deletions

File tree

docs/user-guide/area_calc.ipynb

Lines changed: 1923 additions & 55 deletions
Large diffs are not rendered by default.

test/constants.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
NNODES_outCSne30 = 5402
77
NNODES_outRLL1deg = 64442
88
DATAVARS_outCSne30 = 4
9-
TRI_AREA = 1.047
9+
TRI_AREA = 0.02216612469199045
10+
CORRECTED_TRI_AREA = 0.02244844510268421
1011
# 4*Pi is 12.56
1112
MESH30_AREA = 12.566
1213
PSI_INTG = 12.566

test/test_grid.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,24 +265,27 @@ def test_operators_ne():
265265

266266
def test_face_areas_calculate_total_face_area_triangle():
267267
"""Create a uxarray grid from vertices and saves an exodus file."""
268-
verts = [[[0.57735027, -5.77350269e-01, -0.57735027],
269-
[0.57735027, 5.77350269e-01, -0.57735027],
270-
[-0.57735027, 5.77350269e-01, -0.57735027]]]
268+
verts = [
269+
[[0.02974582, -0.74469018, 0.66674712],
270+
[0.1534193, -0.88744577, 0.43462917],
271+
[0.18363692, -0.72230586, 0.66674712]]
272+
]
271273

272274
grid_verts = ux.open_grid(verts, latlon=False)
273275

274276
# validate the grid
275277
assert grid_verts.validate()
276278

277-
# calculate area
278-
area_gaussian = grid_verts.calculate_total_face_area(
279-
quadrature_rule="gaussian", order=5)
280-
nt.assert_almost_equal(area_gaussian, constants.TRI_AREA, decimal=3)
281-
279+
# calculate area without correction
282280
area_triangular = grid_verts.calculate_total_face_area(
283281
quadrature_rule="triangular", order=4)
284282
nt.assert_almost_equal(area_triangular, constants.TRI_AREA, decimal=1)
285283

284+
# calculate area
285+
area_gaussian = grid_verts.calculate_total_face_area(
286+
quadrature_rule="gaussian", order=5, latitude_adjusted_area=True)
287+
nt.assert_almost_equal(area_gaussian, constants.CORRECTED_TRI_AREA, decimal=3)
288+
286289

287290
def test_face_areas_calculate_total_face_area_file():
288291
"""Create a uxarray grid from vertices and saves an exodus file."""

test/test_helpers.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,41 +32,62 @@
3232
def test_face_area_coords():
3333
"""Test function for helper function get_all_face_area_from_coords."""
3434
# Note: currently only testing one face, but this can be used to get area of multiple faces
35-
x = np.array([0.57735027, 0.57735027, -0.57735027])
36-
y = np.array([-5.77350269e-01, 5.77350269e-01, 5.77350269e-01])
37-
z = np.array([-0.57735027, -0.57735027, -0.57735027])
38-
39-
face_nodes = np.array([[0, 1, 2]]).astype(INT_DTYPE)
35+
# Cartesian coordinates (x, y, z) for each city
36+
# Index 0: Chicago, Index 1: Miami, Index 2: Newburgh, New York, USA.
37+
x = np.array([0.02974582, 0.1534193, 0.18363692])
38+
y = np.array([-0.74469018, -0.88744577, -0.72230586])
39+
z = np.array([0.66674712, 0.43462917, 0.66674712])
40+
face_nodes = np.array([[0, 1, 2]])
4041
face_dimension = np.array([3], dtype=INT_DTYPE)
4142

42-
area, jacobian = ux.grid.area.get_all_face_area_from_coords(
43+
area, _ = ux.grid.area.get_all_face_area_from_coords(
4344
x, y, z, face_nodes, face_dimension, 3, coords_type="cartesian")
45+
nt.assert_almost_equal(area, constants.TRI_AREA, decimal=5)
4446

45-
nt.assert_almost_equal(area, constants.TRI_AREA, decimal=1)
4647

4748
def test_calculate_face_area():
4849
"""Test function for helper function calculate_face_area - only one face."""
4950
# Note: currently only testing one face, but this can be used to get area of multiple faces
5051
# Also note, this does not need face_nodes, assumes nodes are in counterclockwise orientation
51-
x = np.array([0.57735027, 0.57735027, -0.57735027])
52-
y = np.array([-5.77350269e-01, 5.77350269e-01, 5.77350269e-01])
53-
z = np.array([-0.57735027, -0.57735027, -0.57735027])
52+
x = np.array([0.02974582, 0.1534193, 0.18363692])
53+
y = np.array([-0.74469018, -0.88744577, -0.72230586])
54+
z = np.array([0.66674712, 0.43462917, 0.66674712])
55+
56+
area, _ = ux.grid.area.calculate_face_area(
57+
x, y, z, "gaussian", 5, "cartesian", latitude_adjusted_area=False)
58+
59+
nt.assert_almost_equal(area, constants.TRI_AREA, decimal=5)
60+
61+
area_corrected, _ = ux.grid.area.calculate_face_area(
62+
x, y, z, "gaussian", 5, "cartesian", latitude_adjusted_area=True)
5463

55-
area, jacobian = ux.grid.area.calculate_face_area(
56-
x, y, z, "gaussian", 5, "cartesian")
64+
nt.assert_almost_equal(area_corrected, constants.CORRECTED_TRI_AREA, decimal=5)
65+
66+
# Make the same grid using lon/lat check area = constants.TRI_AREA
67+
lon = np.array([-87.7126, -80.1918, -75.7355])
68+
lat = np.array([41.8165, 25.7617, 41.8165])
69+
face_nodes = np.array([[0, 1, 2]])
70+
71+
grid = ux.Grid.from_topology(
72+
node_lon=lon,
73+
node_lat=lat,
74+
face_node_connectivity=face_nodes,
75+
fill_value=-1,
76+
)
5777

58-
nt.assert_almost_equal(area, constants.TRI_AREA, decimal=3)
78+
area, _ = grid.compute_face_areas()
79+
nt.assert_almost_equal(area, constants.TRI_AREA, decimal=5)
5980

6081
def test_quadrature():
6182
order = 1
62-
dG, dW = ux.grid.area.get_tri_quadratureDG(order)
83+
dG, dW = ux.grid.area.get_tri_quadrature_dg(order)
6384
G = np.array([[0.33333333, 0.33333333, 0.33333333]])
6485
W = np.array([1.0])
6586

6687
np.testing.assert_array_almost_equal(G, dG)
6788
np.testing.assert_array_almost_equal(W, dW)
6889

69-
dG, dW = ux.grid.area.get_gauss_quadratureDG(order)
90+
dG, dW = ux.grid.area.get_gauss_quadrature_dg(order)
7091

7192
G = np.array([[0.5]])
7293
W = np.array([1.0])

0 commit comments

Comments
 (0)