-
Notifications
You must be signed in to change notification settings - Fork 168
Structured grids barycentric coordinates #2037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a41c8e5
c427da2
8d6cc6c
db0549d
f3edf12
106236e
feb4a7c
36e4aa7
0861541
c03a8cf
f4e0aad
e8a58aa
ec99f1a
346cbca
1531699
73feee0
fadbfbf
2085971
1166b02
6346183
891ecaa
2e5b593
de0a616
2063abd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,8 @@ | |
| from .grid import GridType | ||
|
|
||
| if TYPE_CHECKING: | ||
| from parcels.xgrid import XGrid | ||
|
|
||
| from .field import Field | ||
| # from .grid import Grid | ||
|
|
||
|
|
@@ -270,6 +272,89 @@ def _search_indices_rectilinear( | |
| return (zeta, eta, xsi, _ei) | ||
|
|
||
|
|
||
| def _search_indices_curvilinear_2d( | ||
| grid: XGrid, y: float, x: float, yi_guess: int | None = None, xi_guess: int | None = None | ||
| ): | ||
| yi, xi = yi_guess, xi_guess | ||
| if yi is None: | ||
| yi = int(grid.ydim / 2) - 1 | ||
|
|
||
| if xi is None: | ||
| xi = int(grid.xdim / 2) - 1 | ||
|
|
||
| xsi = eta = -1.0 | ||
| invA = np.array( | ||
| [ | ||
| [1, 0, 0, 0], | ||
| [-1, 1, 0, 0], | ||
| [-1, 0, 0, 1], | ||
| [1, -1, 1, -1], | ||
| ] | ||
| ) | ||
| maxIterSearch = 1e6 | ||
| it = 0 | ||
| tol = 1.0e-10 | ||
|
|
||
| # # ! Error handling for out of bounds | ||
| # TODO: Re-enable in some capacity | ||
| # if x < field.lonlat_minmax[0] or x > field.lonlat_minmax[1]: | ||
| # if grid.lon[0, 0] < grid.lon[0, -1]: | ||
| # _raise_field_out_of_bound_error(y, x) | ||
| # elif x < grid.lon[0, 0] and x > grid.lon[0, -1]: # This prevents from crashing in [160, -160] | ||
VeckoTheGecko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| # _raise_field_out_of_bound_error(z, y, x) | ||
|
|
||
| # if y < field.lonlat_minmax[2] or y > field.lonlat_minmax[3]: | ||
| # _raise_field_out_of_bound_error(z, y, x) | ||
|
|
||
| while xsi < -tol or xsi > 1 + tol or eta < -tol or eta > 1 + tol: | ||
| px = np.array([grid.lon[yi, xi], grid.lon[yi, xi + 1], grid.lon[yi + 1, xi + 1], grid.lon[yi + 1, xi]]) | ||
|
|
||
| py = np.array([grid.lat[yi, xi], grid.lat[yi, xi + 1], grid.lat[yi + 1, xi + 1], grid.lat[yi + 1, xi]]) | ||
| a = np.dot(invA, px) | ||
| b = np.dot(invA, py) | ||
|
|
||
| aa = a[3] * b[2] - a[2] * b[3] | ||
| bb = a[3] * b[0] - a[0] * b[3] + a[1] * b[2] - a[2] * b[1] + x * b[3] - y * a[3] | ||
| cc = a[1] * b[0] - a[0] * b[1] + x * b[1] - y * a[1] | ||
| if abs(aa) < 1e-12: # Rectilinear cell, or quasi | ||
| eta = -cc / bb | ||
| else: | ||
| det2 = bb * bb - 4 * aa * cc | ||
| if det2 > 0: # so, if det is nan we keep the xsi, eta from previous iter | ||
| det = np.sqrt(det2) | ||
| eta = (-bb + det) / (2 * aa) | ||
| if abs(a[1] + a[3] * eta) < 1e-12: # this happens when recti cell rotated of 90deg | ||
| xsi = ((y - py[0]) / (py[1] - py[0]) + (y - py[3]) / (py[2] - py[3])) * 0.5 | ||
| else: | ||
| xsi = (x - a[0] - a[2] * eta) / (a[1] + a[3] * eta) | ||
| if xsi < 0 and eta < 0 and xi == 0 and yi == 0: | ||
| _raise_field_out_of_bound_error(0, y, x) | ||
| if xsi > 1 and eta > 1 and xi == grid.xdim - 1 and yi == grid.ydim - 1: | ||
| _raise_field_out_of_bound_error(0, y, x) | ||
| if xsi < -tol: | ||
| xi -= 1 | ||
| elif xsi > 1 + tol: | ||
| xi += 1 | ||
| if eta < -tol: | ||
| yi -= 1 | ||
| elif eta > 1 + tol: | ||
| yi += 1 | ||
| (yi, xi) = _reconnect_bnd_indices(yi, xi, grid.ydim, grid.xdim, grid.mesh) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this needed if we don't do periodic grids anymore?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was wondering if this wasn't for periodic grids, but instead was to do with tripolar grids - would that make sense? I thought the edges/wrapping in that grid would result in the index search needing to be "reconnected" to the grid like this.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you may indeed be right. Let's leave in for now and we can see whether this is still necessary when we test curvilinear NEMO grid in the Arctic |
||
| it += 1 | ||
| if it > maxIterSearch: | ||
| print(f"Correct cell not found after {maxIterSearch} iterations") | ||
| _raise_field_out_of_bound_error(0, y, x) | ||
| xsi = max(0.0, xsi) | ||
| eta = max(0.0, eta) | ||
| xsi = min(1.0, xsi) | ||
| eta = min(1.0, eta) | ||
|
|
||
| if not ((0 <= xsi <= 1) and (0 <= eta <= 1)): | ||
| _raise_field_sampling_error(y, x) | ||
|
|
||
| return (yi, eta, xi, xsi) | ||
|
|
||
|
|
||
| ## TODO : Still need to implement the search_indices_curvilinear | ||
| def _search_indices_curvilinear(field: Field, time, z, y, x, ti, particle=None, search2D=False): | ||
| if particle: | ||
VeckoTheGecko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.