@@ -270,6 +270,96 @@ def _search_indices_rectilinear(
270270 return (zeta , eta , xsi , _ei )
271271
272272
273+ ## TODO : Still need to implement the search_indices_curvilinear
274+ def _search_indices_curvilinear_2d (field : Field , time , z , y , x , ti , particle = None , search2D = False ):
275+ if particle :
276+ zi , yi , xi = field .unravel_index (particle .ei )
277+ else :
278+ xi = int (field .xdim / 2 ) - 1
279+ yi = int (field .ydim / 2 ) - 1
280+ xsi = eta = - 1.0
281+ grid = field .grid
282+ invA = np .array ([[1 , 0 , 0 , 0 ], [- 1 , 1 , 0 , 0 ], [- 1 , 0 , 0 , 1 ], [1 , - 1 , 1 , - 1 ]])
283+ maxIterSearch = 1e6
284+ it = 0
285+ tol = 1.0e-10
286+ if not grid .zonal_periodic :
287+ if x < field .lonlat_minmax [0 ] or x > field .lonlat_minmax [1 ]:
288+ if grid .lon [0 , 0 ] < grid .lon [0 , - 1 ]:
289+ _raise_field_out_of_bound_error (z , y , x )
290+ elif x < grid .lon [0 , 0 ] and x > grid .lon [0 , - 1 ]: # This prevents from crashing in [160, -160]
291+ _raise_field_out_of_bound_error (z , y , x )
292+ if y < field .lonlat_minmax [2 ] or y > field .lonlat_minmax [3 ]:
293+ _raise_field_out_of_bound_error (z , y , x )
294+
295+ while xsi < - tol or xsi > 1 + tol or eta < - tol or eta > 1 + tol :
296+ px = np .array ([grid .lon [yi , xi ], grid .lon [yi , xi + 1 ], grid .lon [yi + 1 , xi + 1 ], grid .lon [yi + 1 , xi ]])
297+ if grid .mesh == "spherical" :
298+ px [0 ] = px [0 ] + 360 if px [0 ] < x - 225 else px [0 ]
299+ px [0 ] = px [0 ] - 360 if px [0 ] > x + 225 else px [0 ]
300+ px [1 :] = np .where (px [1 :] - px [0 ] > 180 , px [1 :] - 360 , px [1 :])
301+ px [1 :] = np .where (- px [1 :] + px [0 ] > 180 , px [1 :] + 360 , px [1 :])
302+ py = np .array ([grid .lat [yi , xi ], grid .lat [yi , xi + 1 ], grid .lat [yi + 1 , xi + 1 ], grid .lat [yi + 1 , xi ]])
303+ a = np .dot (invA , px )
304+ b = np .dot (invA , py )
305+
306+ aa = a [3 ] * b [2 ] - a [2 ] * b [3 ]
307+ bb = a [3 ] * b [0 ] - a [0 ] * b [3 ] + a [1 ] * b [2 ] - a [2 ] * b [1 ] + x * b [3 ] - y * a [3 ]
308+ cc = a [1 ] * b [0 ] - a [0 ] * b [1 ] + x * b [1 ] - y * a [1 ]
309+ if abs (aa ) < 1e-12 : # Rectilinear cell, or quasi
310+ eta = - cc / bb
311+ else :
312+ det2 = bb * bb - 4 * aa * cc
313+ if det2 > 0 : # so, if det is nan we keep the xsi, eta from previous iter
314+ det = np .sqrt (det2 )
315+ eta = (- bb + det ) / (2 * aa )
316+ if abs (a [1 ] + a [3 ] * eta ) < 1e-12 : # this happens when recti cell rotated of 90deg
317+ xsi = ((y - py [0 ]) / (py [1 ] - py [0 ]) + (y - py [3 ]) / (py [2 ] - py [3 ])) * 0.5
318+ else :
319+ xsi = (x - a [0 ] - a [2 ] * eta ) / (a [1 ] + a [3 ] * eta )
320+ if xsi < 0 and eta < 0 and xi == 0 and yi == 0 :
321+ _raise_field_out_of_bound_error (0 , y , x )
322+ if xsi > 1 and eta > 1 and xi == grid .xdim - 1 and yi == grid .ydim - 1 :
323+ _raise_field_out_of_bound_error (0 , y , x )
324+ if xsi < - tol :
325+ xi -= 1
326+ elif xsi > 1 + tol :
327+ xi += 1
328+ if eta < - tol :
329+ yi -= 1
330+ elif eta > 1 + tol :
331+ yi += 1
332+ (yi , xi ) = _reconnect_bnd_indices (yi , xi , grid .ydim , grid .xdim , grid .mesh )
333+ it += 1
334+ if it > maxIterSearch :
335+ print (f"Correct cell not found after { maxIterSearch } iterations" )
336+ _raise_field_out_of_bound_error (0 , y , x )
337+ xsi = max (0.0 , xsi )
338+ eta = max (0.0 , eta )
339+ xsi = min (1.0 , xsi )
340+ eta = min (1.0 , eta )
341+
342+ if grid .zdim > 1 and not search2D :
343+ if grid ._gtype == GridType .CurvilinearZGrid :
344+ try :
345+ (zi , zeta ) = search_indices_vertical_z (field .grid , field .gridindexingtype , z )
346+ except FieldOutOfBoundError :
347+ _raise_field_out_of_bound_error (z , y , x )
348+ elif grid ._gtype == GridType .CurvilinearSGrid :
349+ (zi , zeta ) = search_indices_vertical_s (field .grid , field .interp_method , time , z , y , x , ti , yi , xi , eta , xsi )
350+ else :
351+ zi = - 1
352+ zeta = 0
353+
354+ if not ((0 <= xsi <= 1 ) and (0 <= eta <= 1 ) and (0 <= zeta <= 1 )):
355+ _raise_field_sampling_error (z , y , x )
356+
357+ if particle :
358+ particle .ei [field .igrid ] = field .ravel_index (zi , yi , xi )
359+
360+ return (zeta , eta , xsi , zi , yi , xi )
361+
362+
273363## TODO : Still need to implement the search_indices_curvilinear
274364def _search_indices_curvilinear (field : Field , time , z , y , x , ti , particle = None , search2D = False ):
275365 if particle :
0 commit comments