Skip to content

Commit 83fc666

Browse files
Add grid pointer in vectorfield, clean up vectorfield.eval logic
For consistency in the API between a field and vectorfield, the VectorField.grid points to VectorField.U.grid . This is needed since both Field and VectorField objects can be used in a FieldSet and it would be cumbersome to have logic switch how a `grid` is obtained based on whether a fieldset attribute is a Field or VectorField. VectorField.eval logic now follows a similar execution pattern to the Field.eval logic, except when the VectorField._interp_method is not provided. When VectorField._interp_method is not provided, interpolation falls back to component-wise interpolation using the VectorField.[U,V,W]._interp_method's.
1 parent 853b84d commit 83fc666

1 file changed

Lines changed: 38 additions & 29 deletions

File tree

parcels/field.py

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,10 @@ def eval(self, time: datetime, z, y, x, particle=None, applyConversion=True):
309309
conversion to the result. Note that we defer to
310310
scipy.interpolate to perform spatial interpolation.
311311
"""
312-
if particle is None:
313-
_ei = None
314-
else:
315-
_ei = particle.ei[self.igrid]
312+
# if particle is None:
313+
_ei = None
314+
# else:
315+
# _ei = particle.ei[self.igrid]
316316

317317
try:
318318
tau, ti = _search_time_index(self, time)
@@ -386,6 +386,7 @@ def __init__(
386386
self.U = U
387387
self.V = V
388388
self.W = W
389+
self.grid = U.grid
389390

390391
if W is None:
391392
assert_same_time_interval((U, V))
@@ -430,41 +431,49 @@ def vector_interp_method(self, method: Callable):
430431
# and np.allclose(grid1.depth, grid2.depth)
431432
# and np.allclose(grid1.time, grid2.time)
432433
# )
433-
def _interpolate(self, time, z, y, x, ei):
434-
bcoords, _ei, ti = self._search_indices(time, z, y, x, ei=ei)
434+
def eval(self, time: datetime, z, y, x, particle=None, applyConversion=True):
435+
"""Interpolate field values in space and time.
435436
436-
if self._vector_interp_method is None:
437-
u = self.U.eval(time, z, y, x, _ei, applyConversion=False)
438-
v = self.V.eval(time, z, y, x, _ei, applyConversion=False)
439-
if "3D" in self.vector_type:
440-
w = self.W.eval(time, z, y, x, _ei, applyConversion=False)
441-
return (u, v, w)
442-
else:
443-
return (u, v, 0)
444-
else:
445-
(u, v, w) = self._vector_interp_method(ti, _ei, bcoords, time, z, y, x)
446-
return (u, v, w)
437+
We interpolate linearly in time and apply implicit unit
438+
conversion to the result. Note that we defer to
439+
scipy.interpolate to perform spatial interpolation.
440+
"""
441+
# if particle is None:
442+
_ei = None
443+
# else:
444+
# _ei = particle.ei[self.igrid]
447445

448-
def eval(self, time, z, y, x, ei=None, applyConversion=True):
449-
if ei is None:
450-
_ei = 0
451-
else:
452-
_ei = ei[self.igrid]
446+
try:
447+
tau, ti = _search_time_index(self.U, time)
448+
bcoords, _ei = self.grid.search(z, y, x, ei=_ei)
449+
if self._vector_interp_method is None:
450+
u = self.U._interp_method(self.U, ti, _ei, bcoords, tau, time, z, y, x)
451+
v = self.V._interp_method(self.V, ti, _ei, bcoords, tau, time, z, y, x)
452+
if "3D" in self.vector_type:
453+
w = self.W._interp_method(self.W, ti, _ei, bcoords, tau, time, z, y, x)
454+
else:
455+
(u, v, w) = self._vector_interp_method(self, ti, _ei, bcoords, time, z, y, x)
453456

454-
(u, v, w) = self._interpolate(time, z, y, x, _ei)
457+
# print(u,v)
458+
if applyConversion:
459+
u = self.U.units.to_target(u, z, y, x)
460+
v = self.V.units.to_target(v, z, y, x)
461+
if "3D" in self.vector_type:
462+
w = self.W.units.to_target(w, z, y, x) if self.W else 0.0
455463

456-
if applyConversion:
457-
u = self.U.units.to_target(u, z, y, x)
458-
v = self.V.units.to_target(v, z, y, x)
459464
if "3D" in self.vector_type:
460-
w = self.W.units.to_target(w, z, y, x)
465+
return (u, v, w)
466+
else:
467+
return (u, v)
461468

462-
return (u, v, w)
469+
except (FieldSamplingError, FieldOutOfBoundError, FieldOutOfBoundSurfaceError) as e:
470+
e.add_note(f"Error interpolating field '{self.name}'.")
471+
raise e
463472

464473
def __getitem__(self, key):
465474
try:
466475
if _isParticle(key):
467-
return self.eval(key.time, key.depth, key.lat, key.lon, key.ei)
476+
return self.eval(key.time, key.depth, key.lat, key.lon, key)
468477
else:
469478
return self.eval(*key)
470479
except tuple(AllParcelsErrorCodes.keys()) as error:

0 commit comments

Comments
 (0)