@@ -746,172 +746,3 @@ def test_dual_duplicate():
746746 dataset = ux .open_dataset (gridfile_geoflow , gridfile_geoflow )
747747 with pytest .raises (RuntimeError ):
748748 dataset .get_dual ()
749-
750-
751- def test_dual_mesh_parallel ():
752- """Test dual mesh construction with parallel processing enabled."""
753- import numba
754- from uxarray .grid .dual import construct_faces
755-
756- # Test with a simple grid
757- grid = ux .open_grid (gridfile_mpas , use_dual = False )
758-
759- # Get the inputs for construct_faces
760- dual_node_x = grid .face_x .values
761- dual_node_y = grid .face_y .values
762- dual_node_z = grid .face_z .values
763- node_x = grid .node_x .values
764- node_y = grid .node_y .values
765- node_z = grid .node_z .values
766- node_face_connectivity = grid .node_face_connectivity .values
767-
768- # Get an array with the number of edges for each face
769- n_edges_mask = node_face_connectivity != INT_FILL_VALUE
770- n_edges = np .sum (n_edges_mask , axis = 1 )
771- max_edges = len (node_face_connectivity [0 ])
772-
773- valid_node_indices = np .where (n_edges >= 3 )[0 ]
774- construct_node_face_connectivity = np .full (
775- (len (valid_node_indices ), max_edges ), INT_FILL_VALUE , dtype = INT_DTYPE
776- )
777-
778- # Test that construct_faces works (this tests the numba compilation)
779- try :
780- result = construct_faces (
781- valid_node_indices ,
782- n_edges ,
783- dual_node_x ,
784- dual_node_y ,
785- dual_node_z ,
786- node_face_connectivity ,
787- node_x ,
788- node_y ,
789- node_z ,
790- construct_node_face_connectivity ,
791- max_edges ,
792- )
793-
794- # Verify the result has the expected shape and properties
795- assert result is not None
796- assert result .dtype == INT_DTYPE
797- assert result .ndim == 2
798-
799- # Compare with the standard dual construction
800- dual = grid .get_dual ()
801- expected_shape = dual .face_node_connectivity .values .shape
802-
803- # The shapes should match since we're using the same algorithm
804- assert result .shape == expected_shape
805-
806- except numba .errors .NumbaError as e :
807- pytest .skip (f"Numba compilation failed: { e } " )
808- except Exception as e :
809- pytest .fail (f"Dual mesh parallel construction failed: { e } " )
810-
811-
812- def test_dual_mesh_parallel_validation ():
813- """Test that parallel dual construction produces identical results and validates threading."""
814- import time
815- from uxarray .grid .dual import construct_faces
816-
817- grid = ux .open_grid (gridfile_mpas , use_dual = False )
818-
819- # Prepare inputs for direct function call
820- dual_node_x = grid .face_x .values
821- dual_node_y = grid .face_y .values
822- dual_node_z = grid .face_z .values
823- node_x = grid .node_x .values
824- node_y = grid .node_y .values
825- node_z = grid .node_z .values
826- node_face_connectivity = grid .node_face_connectivity .values
827-
828- n_edges_mask = node_face_connectivity != INT_FILL_VALUE
829- n_edges = np .sum (n_edges_mask , axis = 1 )
830- max_edges = node_face_connectivity .shape [1 ]
831-
832- valid_node_indices = np .where (n_edges >= 3 )[0 ]
833-
834- # Test multiple runs for consistency
835- results = []
836- times = []
837-
838- for i in range (3 ):
839- construct_node_face_connectivity = np .full (
840- (len (valid_node_indices ), max_edges ), INT_FILL_VALUE , dtype = INT_DTYPE
841- )
842-
843- start_time = time .time ()
844- result = construct_faces (
845- valid_node_indices ,
846- n_edges ,
847- dual_node_x ,
848- dual_node_y ,
849- dual_node_z ,
850- node_face_connectivity ,
851- node_x ,
852- node_y ,
853- node_z ,
854- construct_node_face_connectivity ,
855- max_edges ,
856- )
857- elapsed = time .time () - start_time
858-
859- results .append (result )
860- times .append (elapsed )
861-
862- # Verify all results are identical (parallel consistency)
863- for i in range (1 , len (results )):
864- nt .assert_array_equal (results [0 ], results [i ],
865- err_msg = f"Parallel dual construction run { i } differs from run 0" )
866-
867- # Verify results are valid
868- for result in results :
869- assert result is not None
870- assert result .dtype == INT_DTYPE
871- assert result .ndim == 2
872- assert result .shape [0 ] == len (valid_node_indices )
873- assert result .shape [1 ] == max_edges
874-
875- # Verify performance is reasonable (should complete in reasonable time)
876- avg_time = np .mean (times )
877- assert avg_time < 30.0 , f"Dual construction too slow: { avg_time :.2f} s"
878-
879- # Verify against standard implementation
880- dual_standard = grid .get_dual ()
881- assert results [0 ].shape == dual_standard .face_node_connectivity .values .shape
882-
883-
884- def test_normalize_existing_coordinates_non_norm_initial ():
885- gridfile_mpas = current_path / "meshfiles" / "mpas" / "QU" / "mesh.QU.1920km.151026.nc"
886- from uxarray .grid .validation import _check_normalization
887- uxgrid = ux .open_grid (gridfile_mpas )
888-
889- uxgrid .node_x .data = 5 * uxgrid .node_x .data
890- uxgrid .node_y .data = 5 * uxgrid .node_y .data
891- uxgrid .node_z .data = 5 * uxgrid .node_z .data
892- assert not _check_normalization (uxgrid )
893-
894- uxgrid .normalize_cartesian_coordinates ()
895- assert _check_normalization (uxgrid )
896-
897-
898- def test_normalize_existing_coordinates_norm_initial ():
899- gridfile_CSne30 = current_path / "meshfiles" / "ugrid" / "outCSne30" / "outCSne30.ug"
900- from uxarray .grid .validation import _check_normalization
901- uxgrid = ux .open_grid (gridfile_CSne30 )
902-
903- assert _check_normalization (uxgrid )
904-
905-
906-
907- def test_from_topology ():
908- node_lon = np .array ([- 20.0 , 0.0 , 20.0 , - 20 , - 40 ])
909- node_lat = np .array ([- 10.0 , 10.0 , - 10.0 , 10 , - 10 ])
910- face_node_connectivity = np .array ([[0 , 1 , 2 , - 1 ], [0 , 1 , 3 , 4 ]])
911-
912- uxgrid = ux .Grid .from_topology (
913- node_lon = node_lon ,
914- node_lat = node_lat ,
915- face_node_connectivity = face_node_connectivity ,
916- fill_value = - 1 ,
917- )
0 commit comments