Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
454 changes: 191 additions & 263 deletions docs/examples/tutorial_stommel_uxarray.ipynb

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions parcels/_datasets/unstructured/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ def _stommel_gyre_delaunay():
uxgrid.attrs["Conventions"] = "UGRID-1.0"

# Define arrays U (zonal), V (meridional) and P (sea surface height)
U = np.zeros((1, nz1, lat.size), dtype=np.float64)
V = np.zeros((1, nz1, lat.size), dtype=np.float64)
U = np.zeros((1, nz1, uxgrid.n_face), dtype=np.float64)
V = np.zeros((1, nz1, uxgrid.n_face), dtype=np.float64)
W = np.zeros((1, nz, lat.size), dtype=np.float64)
P = np.zeros((1, nz1, lat.size), dtype=np.float64)
P = np.zeros((1, nz1, uxgrid.n_face), dtype=np.float64)

for i, (x, y) in enumerate(zip(lon_flat, lat_flat, strict=False)):
for i, (x, y) in enumerate(zip(uxgrid.face_lon, uxgrid.face_lat, strict=False)):
xi = x / 60.0
yi = y / 60.0

Expand All @@ -61,10 +61,10 @@ def _stommel_gyre_delaunay():
data=U,
name="U",
uxgrid=uxgrid,
dims=["time", "nz1", "n_node"],
dims=["time", "nz1", "n_face"],
coords=dict(
time=(["time"], [TIME[0]]),
nz1=(["nz1"], [0]),
nz1=(["nz1"], zc),
),
attrs=dict(
description="zonal velocity", units="m/s", location="node", mesh="delaunay", Conventions="UGRID-1.0"
Expand All @@ -74,7 +74,7 @@ def _stommel_gyre_delaunay():
data=V,
name="V",
uxgrid=uxgrid,
dims=["time", "nz1", "n_node"],
dims=["time", "nz1", "n_face"],
coords=dict(
time=(["time"], [TIME[0]]),
nz1=(["nz1"], zc),
Expand All @@ -100,7 +100,7 @@ def _stommel_gyre_delaunay():
data=P,
name="p",
uxgrid=uxgrid,
dims=["time", "nz1", "n_node"],
dims=["time", "nz1", "n_face"],
coords=dict(
time=(["time"], [TIME[0]]),
nz1=(["nz1"], zc),
Expand Down
2 changes: 1 addition & 1 deletion parcels/_index_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
if the sampled value is outside the time value range.
"""
if field.time_interval is None:
return 0
return 0, 0

Check warning on line 41 in parcels/_index_search.py

View check run for this annotation

Codecov / codecov/patch

parcels/_index_search.py#L41

Added line #L41 was not covered by tests

if time not in field.time_interval:
_raise_time_extrapolation_error(time, field=None)
Expand Down
67 changes: 38 additions & 29 deletions parcels/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,10 @@
conversion to the result. Note that we defer to
scipy.interpolate to perform spatial interpolation.
"""
if particle is None:
_ei = None
else:
_ei = particle.ei[self.igrid]
# if particle is None:
_ei = None
# else:
# _ei = particle.ei[self.igrid]

try:
tau, ti = _search_time_index(self, time)
Expand Down Expand Up @@ -386,6 +386,7 @@
self.U = U
self.V = V
self.W = W
self.grid = U.grid

if W is None:
assert_same_time_interval((U, V))
Expand Down Expand Up @@ -430,41 +431,49 @@
# and np.allclose(grid1.depth, grid2.depth)
# and np.allclose(grid1.time, grid2.time)
# )
def _interpolate(self, time, z, y, x, ei):
bcoords, _ei, ti = self._search_indices(time, z, y, x, ei=ei)
def eval(self, time: datetime, z, y, x, particle=None, applyConversion=True):
"""Interpolate field values in space and time.

if self._vector_interp_method is None:
u = self.U.eval(time, z, y, x, _ei, applyConversion=False)
v = self.V.eval(time, z, y, x, _ei, applyConversion=False)
if "3D" in self.vector_type:
w = self.W.eval(time, z, y, x, _ei, applyConversion=False)
return (u, v, w)
else:
return (u, v, 0)
else:
(u, v, w) = self._vector_interp_method(ti, _ei, bcoords, time, z, y, x)
return (u, v, w)
We interpolate linearly in time and apply implicit unit
conversion to the result. Note that we defer to
scipy.interpolate to perform spatial interpolation.
"""
# if particle is None:
_ei = None

Check warning on line 442 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L442

Added line #L442 was not covered by tests
# else:
# _ei = particle.ei[self.igrid]

def eval(self, time, z, y, x, ei=None, applyConversion=True):
if ei is None:
_ei = 0
else:
_ei = ei[self.igrid]
try:
tau, ti = _search_time_index(self.U, time)
bcoords, _ei = self.grid.search(z, y, x, ei=_ei)
if self._vector_interp_method is None:
u = self.U._interp_method(self.U, ti, _ei, bcoords, tau, time, z, y, x)
v = self.V._interp_method(self.V, ti, _ei, bcoords, tau, time, z, y, x)
if "3D" in self.vector_type:
w = self.W._interp_method(self.W, ti, _ei, bcoords, tau, time, z, y, x)

Check warning on line 453 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L446-L453

Added lines #L446 - L453 were not covered by tests
else:
(u, v, w) = self._vector_interp_method(self, ti, _ei, bcoords, time, z, y, x)

Check warning on line 455 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L455

Added line #L455 was not covered by tests

(u, v, w) = self._interpolate(time, z, y, x, _ei)
# print(u,v)
if applyConversion:
u = self.U.units.to_target(u, z, y, x)
v = self.V.units.to_target(v, z, y, x)
if "3D" in self.vector_type:
w = self.W.units.to_target(w, z, y, x) if self.W else 0.0

Check warning on line 462 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L458-L462

Added lines #L458 - L462 were not covered by tests

if applyConversion:
u = self.U.units.to_target(u, z, y, x)
v = self.V.units.to_target(v, z, y, x)
if "3D" in self.vector_type:
w = self.W.units.to_target(w, z, y, x)
return (u, v, w)

Check warning on line 465 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L465

Added line #L465 was not covered by tests
else:
return (u, v)

Check warning on line 467 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L467

Added line #L467 was not covered by tests

return (u, v, w)
except (FieldSamplingError, FieldOutOfBoundError, FieldOutOfBoundSurfaceError) as e:
e.add_note(f"Error interpolating field '{self.name}'.")
raise e

Check warning on line 471 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L469-L471

Added lines #L469 - L471 were not covered by tests

def __getitem__(self, key):
try:
if _isParticle(key):
return self.eval(key.time, key.depth, key.lat, key.lon, key.ei)
return self.eval(key.time, key.depth, key.lat, key.lon, key)

Check warning on line 476 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L476

Added line #L476 was not covered by tests
else:
return self.eval(*key)
except tuple(AllParcelsErrorCodes.keys()) as error:
Expand Down
Loading
Loading