@@ -102,6 +102,23 @@ def curvilinear_point_in_cell(grid, y: np.ndarray, x: np.ndarray, yi: np.ndarray
102102 )
103103
104104 px = np .array ([grid .lon [yi , xi ], grid .lon [yi , xi + 1 ], grid .lon [yi + 1 , xi + 1 ], grid .lon [yi + 1 , xi ]])
105+ # Map grid and particle longitudes to [-180,180)
106+ px = ((px + 180.0 ) % 360.0 ) - 180.0
107+ x = ((x + 180.0 ) % 360.0 ) - 180.0
108+
109+ # Create a mask for antimeridian cells
110+ lon_span = px .max (axis = 0 ) - px .min (axis = 0 )
111+ antimeridian_cell = lon_span > 180.0
112+
113+ if np .any (antimeridian_cell ):
114+ # For any antimeridian cell ...
115+ # If particle longitude is closer to 180.0, then negative cell longitudes need to be bumped by +360
116+ mask = (px < 0.0 ) & antimeridian_cell [np .newaxis , :] & (x [np .newaxis , :] > 0.0 )
117+ px [mask ] += 360.0
118+ # If particle longitude is closer to -180.0, then positive cell longitudes need to be bumped by -360
119+ mask = (px > 0.0 ) & antimeridian_cell [np .newaxis , :] & (x [np .newaxis , :] < 0.0 )
120+ px [mask ] -= 360.0
121+
105122 py = np .array ([grid .lat [yi , xi ], grid .lat [yi , xi + 1 ], grid .lat [yi + 1 , xi + 1 ], grid .lat [yi + 1 , xi ]])
106123
107124 a , b = np .dot (invA , px ), np .dot (invA , py )
@@ -119,7 +136,6 @@ def curvilinear_point_in_cell(grid, y: np.ndarray, x: np.ndarray, yi: np.ndarray
119136 ((y - py [0 ]) / (py [1 ] - py [0 ]) + (y - py [3 ]) / (py [2 ] - py [3 ])) * 0.5 ,
120137 (x - a [0 ] - a [2 ] * eta ) / (a [1 ] + a [3 ] * eta ),
121138 )
122-
123139 is_in_cell = np .where ((xsi >= 0 ) & (xsi <= 1 ) & (eta >= 0 ) & (eta <= 1 ), 1 , 0 )
124140
125141 return is_in_cell , np .column_stack ((xsi , eta ))
0 commit comments