22import pytest
33
44import uxarray as ux
5+ from uxarray .remap .yac import YacNotAvailableError , _import_yac
56
67
7- yac = pytest .importorskip ("yac" )
8+ try :
9+ _import_yac ()
10+ except YacNotAvailableError :
11+ pytest .skip ("yac.core is not available" , allow_module_level = True )
812
913
1014def test_yac_nnn_node_remap (gridpath , datasetpath ):
@@ -28,7 +32,7 @@ def test_yac_conservative_face_remap(gridpath):
2832 uxds = ux .open_dataset (mesh_path , mesh_path )
2933 dest = ux .open_grid (mesh_path )
3034
31- out = uxds ["latCell" ].remap . nearest_neighbor (
35+ out = uxds ["latCell" ].remap (
3236 destination_grid = dest ,
3337 remap_to = "faces" ,
3438 backend = "yac" ,
@@ -62,3 +66,179 @@ def test_yac_matches_uxarray_nearest_neighbor():
6266 )
6367 assert ux_out .shape == yac_out .shape
6468 assert (ux_out .values == yac_out .values ).all ()
69+
70+
71+ def test_yac_call_defaults_to_nnn ():
72+ verts = np .array ([(0.0 , 90.0 ), (- 180.0 , 0.0 ), (0.0 , - 90.0 )])
73+ grid = ux .open_grid (verts )
74+ da = ux .UxDataArray (
75+ np .asarray ([1.0 , 2.0 , 3.0 ]),
76+ dims = ["n_node" ],
77+ coords = {"n_node" : [0 , 1 , 2 ]},
78+ uxgrid = grid ,
79+ )
80+
81+ out = da .remap (
82+ destination_grid = grid ,
83+ remap_to = "nodes" ,
84+ backend = "yac" ,
85+ )
86+
87+ assert out .shape == da .shape
88+ np .testing .assert_array_equal (out .values , da .values )
89+
90+
91+ def test_yac_invalid_backend_raises ():
92+ verts = np .array ([(0.0 , 90.0 ), (- 180.0 , 0.0 ), (0.0 , - 90.0 )])
93+ grid = ux .open_grid (verts )
94+ da = ux .UxDataArray (
95+ np .asarray ([1.0 , 2.0 , 3.0 ]),
96+ dims = ["n_node" ],
97+ coords = {"n_node" : [0 , 1 , 2 ]},
98+ uxgrid = grid ,
99+ )
100+
101+ with pytest .raises (ValueError , match = "Invalid backend" ):
102+ da .remap .nearest_neighbor (
103+ destination_grid = grid ,
104+ remap_to = "nodes" ,
105+ backend = "bogus" ,
106+ )
107+
108+
109+ def test_yac_idw_not_implemented ():
110+ verts = np .array ([(0.0 , 90.0 ), (- 180.0 , 0.0 ), (0.0 , - 90.0 )])
111+ grid = ux .open_grid (verts )
112+ da = ux .UxDataArray (
113+ np .asarray ([1.0 , 2.0 , 3.0 ]),
114+ dims = ["n_node" ],
115+ coords = {"n_node" : [0 , 1 , 2 ]},
116+ uxgrid = grid ,
117+ )
118+
119+ with pytest .raises (NotImplementedError , match = "inverse_distance_weighted" ):
120+ da .remap .inverse_distance_weighted (
121+ destination_grid = grid ,
122+ remap_to = "nodes" ,
123+ backend = "yac" ,
124+ yac_method = "nnn" ,
125+ yac_options = {"n" : 1 },
126+ )
127+
128+
129+ def test_yac_bilinear_face_remap (gridpath ):
130+ mesh_path = gridpath ("mpas" , "QU" , "mesh.QU.1920km.151026.nc" )
131+ uxds = ux .open_dataset (mesh_path , mesh_path )
132+ dest = ux .open_grid (mesh_path )
133+
134+ out = uxds ["latCell" ].remap .bilinear (
135+ destination_grid = dest ,
136+ remap_to = "faces" ,
137+ backend = "yac" ,
138+ )
139+
140+ assert out .size == dest .n_face
141+
142+
143+ def test_yac_conservative_rejects_non_face_data ():
144+ verts = np .array ([(0.0 , 90.0 ), (- 180.0 , 0.0 ), (0.0 , - 90.0 )])
145+ grid = ux .open_grid (verts )
146+ da = ux .UxDataArray (
147+ np .asarray ([1.0 , 2.0 , 3.0 ]),
148+ dims = ["n_node" ],
149+ coords = {"n_node" : [0 , 1 , 2 ]},
150+ uxgrid = grid ,
151+ )
152+
153+ with pytest .raises (ValueError , match = "face-centered" ):
154+ da .remap .nearest_neighbor (
155+ destination_grid = grid ,
156+ remap_to = "nodes" ,
157+ backend = "yac" ,
158+ yac_method = "conservative" ,
159+ yac_options = {"order" : 1 },
160+ )
161+
162+
163+ def test_yac_preserves_spatial_coordinate_remap ():
164+ verts = np .array ([(0.0 , 90.0 ), (- 180.0 , 0.0 ), (0.0 , - 90.0 )])
165+ grid = ux .open_grid (verts )
166+ da = ux .UxDataArray (
167+ np .asarray ([1.0 , 2.0 , 3.0 ]),
168+ dims = ["n_node" ],
169+ coords = {
170+ "n_node" : [0 , 1 , 2 ],
171+ "node_lon" : (
172+ "n_node" ,
173+ np .array ([0.0 , - 180.0 , 0.0 ]),
174+ {"standard_name" : "longitude" , "units" : "degrees_east" },
175+ ),
176+ "node_lat" : (
177+ "n_node" ,
178+ np .array ([90.0 , 0.0 , - 90.0 ]),
179+ {"standard_name" : "latitude" , "units" : "degrees_north" },
180+ ),
181+ },
182+ uxgrid = grid ,
183+ )
184+
185+ out = da .remap .nearest_neighbor (
186+ destination_grid = grid ,
187+ remap_to = "nodes" ,
188+ backend = "yac" ,
189+ yac_method = "nnn" ,
190+ yac_options = {"n" : 1 },
191+ )
192+
193+ np .testing .assert_array_equal (out .values , da .values )
194+ assert "node_lon" in out .coords
195+ assert "node_lat" in out .coords
196+
197+
198+ def test_yac_batched_remap_with_extra_dimension ():
199+ verts = np .array ([(0.0 , 90.0 ), (- 180.0 , 0.0 ), (0.0 , - 90.0 )])
200+ grid = ux .open_grid (verts )
201+ da = ux .UxDataArray (
202+ np .asarray ([[1.0 , 2.0 , 3.0 ], [10.0 , 20.0 , 30.0 ]]),
203+ dims = ["time" , "n_node" ],
204+ coords = {"time" : [0 , 1 ], "n_node" : [0 , 1 , 2 ]},
205+ uxgrid = grid ,
206+ )
207+
208+ out = da .remap .nearest_neighbor (
209+ destination_grid = grid ,
210+ remap_to = "nodes" ,
211+ backend = "yac" ,
212+ yac_method = "nnn" ,
213+ yac_options = {"n" : 1 },
214+ )
215+
216+ assert out .shape == da .shape
217+ np .testing .assert_array_equal (out .values , da .values )
218+
219+
220+ def test_yac_batched_remap_with_fractional_mask ():
221+ verts = np .array ([(0.0 , 90.0 ), (- 180.0 , 0.0 ), (0.0 , - 90.0 )])
222+ grid = ux .open_grid (verts )
223+ da = ux .UxDataArray (
224+ np .asarray ([[1.0 , 2.0 , 3.0 ], [10.0 , 20.0 , 30.0 ]]),
225+ dims = ["time" , "n_node" ],
226+ coords = {"time" : [0 , 1 ], "n_node" : [0 , 1 , 2 ]},
227+ uxgrid = grid ,
228+ )
229+ frac_mask = np .ones_like (da .values , dtype = np .float64 )
230+
231+ out = da .remap .nearest_neighbor (
232+ destination_grid = grid ,
233+ remap_to = "nodes" ,
234+ backend = "yac" ,
235+ yac_method = "nnn" ,
236+ yac_options = {
237+ "n" : 1 ,
238+ "frac_mask_fallback_value" : 0.0 ,
239+ "frac_mask" : frac_mask ,
240+ },
241+ )
242+
243+ assert out .shape == da .shape
244+ np .testing .assert_array_equal (out .values , da .values )
0 commit comments