@@ -133,3 +133,100 @@ def test_distance_units():
133133
134134 nt .assert_array_almost_equal (uxgrid ['edge_node_distances' ].values , (xrds ['dvEdge' ].values / xrds .attrs ['sphere_radius' ]))
135135 nt .assert_array_almost_equal (uxgrid ['edge_face_distances' ].values , (xrds ['dcEdge' ].values / xrds .attrs ['sphere_radius' ]))
136+
137+
138+ def test_ocean_mesh_normalization ():
139+ """Test that MPAS ocean mesh with non-unit sphere radius is properly normalized."""
140+ # Ocean mesh has sphere_radius = 6371229.0 meters
141+ uxgrid = ux .open_grid (mpas_ocean_mesh , use_dual = False )
142+
143+ # Check node coordinates are normalized to unit sphere
144+ node_x = uxgrid ._ds ['node_x' ].values
145+ node_y = uxgrid ._ds ['node_y' ].values
146+ node_z = uxgrid ._ds ['node_z' ].values
147+
148+ # Compute radius for each node
149+ radii = np .sqrt (node_x ** 2 + node_y ** 2 + node_z ** 2 )
150+
151+ # All radii should be 1.0 (unit sphere)
152+ nt .assert_array_almost_equal (radii , np .ones_like (radii ), decimal = 10 )
153+
154+ # Check face areas are normalized for unit sphere
155+ # Ocean mesh only covers ~70% of sphere (ocean area)
156+ face_areas = uxgrid .face_areas .values
157+
158+ # Check that all face areas are positive
159+ assert np .all (face_areas > 0 ), "All face areas should be positive"
160+
161+ # Total area should be less than full sphere (4*pi) but reasonable
162+ total_area = np .sum (face_areas )
163+ full_sphere_area = 4.0 * np .pi
164+ assert 0.5 < total_area < full_sphere_area , f"Total area { total_area } should be between 0.5 and { full_sphere_area } "
165+
166+ # Check that individual face areas are reasonable for unit sphere
167+ max_face_area = np .max (face_areas )
168+ min_face_area = np .min (face_areas )
169+ assert max_face_area < 0.1 * full_sphere_area , "Maximum face area seems too large for unit sphere"
170+ assert min_face_area > 1e-10 , "Minimum face area seems too small"
171+
172+ # Check edge lengths are normalized for unit sphere
173+ if "edge_node_distances" in uxgrid ._ds :
174+ edge_lengths = uxgrid ._ds ["edge_node_distances" ].values
175+
176+ # All edge lengths should be positive and <= pi
177+ assert np .all (edge_lengths > 0 ), "All edge lengths should be positive"
178+ assert np .max (edge_lengths ) <= np .pi , "Edge lengths should not exceed pi on unit sphere"
179+
180+
181+ def test_grid_normalization ():
182+ """Test that MPAS grid coordinates are properly normalized."""
183+ uxgrid = ux .open_grid (mpas_grid_path , use_dual = False )
184+
185+ # Check node coordinates are normalized
186+ node_lon = uxgrid ._ds ['node_lon' ].values
187+ node_lat = uxgrid ._ds ['node_lat' ].values
188+ node_x = uxgrid ._ds ['node_x' ].values
189+ node_y = uxgrid ._ds ['node_y' ].values
190+ node_z = uxgrid ._ds ['node_z' ].values
191+
192+ # Compute radius for each node
193+ radii = np .sqrt (node_x ** 2 + node_y ** 2 + node_z ** 2 )
194+
195+ # All radii should be 1.0 (unit sphere)
196+ nt .assert_array_almost_equal (radii , np .ones_like (radii ), decimal = 10 )
197+
198+ # Check face areas are normalized for unit sphere
199+ # Total surface area of unit sphere is 4*pi
200+ expected_total_area = 4.0 * np .pi
201+
202+ # Get face areas
203+ face_areas = uxgrid .face_areas .values
204+
205+ # Check that all face areas are positive
206+ assert np .all (face_areas > 0 ), "All face areas should be positive"
207+
208+ # Check that total area equals surface area of unit sphere
209+ total_area = np .sum (face_areas )
210+ nt .assert_almost_equal (total_area , expected_total_area , decimal = 7 )
211+
212+ # Check that face areas are reasonable (not too small or too large)
213+ # For a unit sphere, face areas should be much smaller than total area
214+ max_face_area = np .max (face_areas )
215+ min_face_area = np .min (face_areas )
216+
217+ assert max_face_area < 0.1 * expected_total_area , "Maximum face area seems too large for unit sphere"
218+ assert min_face_area > 1e-10 , "Minimum face area seems too small"
219+
220+ # Check edge lengths are normalized for unit sphere
221+ # Edge lengths should be reasonable for a unit sphere (max possible is pi for antipodal points)
222+ if "edge_node_distances" in uxgrid ._ds :
223+ edge_lengths = uxgrid ._ds ["edge_node_distances" ].values
224+
225+ # All edge lengths should be positive
226+ assert np .all (edge_lengths > 0 ), "All edge lengths should be positive"
227+
228+ # Maximum edge length on unit sphere cannot exceed pi
229+ assert np .max (edge_lengths ) <= np .pi , "Edge lengths should not exceed pi on unit sphere"
230+
231+ # Minimum edge length should be reasonable
232+ assert np .min (edge_lengths ) > 1e-10 , "Minimum edge length seems too small"
0 commit comments