Skip to content

Commit 5bf0ef8

Browse files
committed
Adding a simple unbeaching kernel that doesn't rely on an unbeaching field.
1 parent c39c8d9 commit 5bf0ef8

1 file changed

Lines changed: 99 additions & 0 deletions

File tree

plasticparcels/kernels.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ def VerticalMixing(particle, fieldset, time):
534534
# Update particle position
535535
particle_ddepth += ddepth # noqa
536536

537+
537538
def reflectAtSurface(particle, fieldset, time):
538539
"""A reflecting boundary condition kernel at the ocean surface.
539540
@@ -595,6 +596,103 @@ def unbeaching(particle, fieldset, time):
595596
particle_dlon += dlon # noqa
596597
particle_dlat += dlat # noqa
597598

599+
def unbeachingBySamplingAfterwards(particle, fieldset, time):
600+
"""Alternative unbeaching kernel.
601+
602+
Description
603+
----------
604+
A kernel to 'unbeach' particles that have been advected onto non-ocean grid cells.
605+
This kernel samples the velocity field in the four cardinal directions around the particle,
606+
and moves the particle in the direction of the highest velocity magnitude, assuming that
607+
this direction is the ocean direction. This kernel only acts if the particle displacement
608+
in both zonal and meridional directions is (near) zero, indicating that the particle is beached.
609+
610+
Parameter Requirements
611+
----------
612+
Fieldset:
613+
None
614+
615+
Kernel Requirements
616+
----------
617+
Order of Operations:
618+
This kernel should be performed after all other movement kernels.
619+
"""
620+
# In the case of being beached, these displacement will be zero
621+
new_lon = particle.lon + particle_dlon
622+
new_lat = particle.lat + particle_dlat
623+
new_depth = particle.depth + particle_ddepth
624+
625+
if math.fabs(particle_dlon) + math.fabs(particle_dlat) < 1e-14:
626+
displacement = 1./8. # Degree displacement to sample the velocity field
627+
628+
# Convert 1m/s to degrees/s at the particle latitude in zonal and meridional directions
629+
unbeach_U = 1. / (1852. * 60. * math.cos(particle.lat * math.pi / 180.))
630+
unbeach_V = 1. / (1852. * 60.)
631+
632+
# Sample the velocity field in the four cardinal directions
633+
(U_left, V_left) = fieldset.UV[time, new_depth, new_lat, new_lon - displacement]
634+
(U_right, V_right) = fieldset.UV[time, new_depth, new_lat, new_lon + displacement]
635+
(U_up, V_up) = fieldset.UV[time, new_depth, new_lat + displacement, new_lon]
636+
(U_down, V_down) = fieldset.UV[time, new_depth, new_lat - displacement, new_lon]
637+
638+
# Find the direction of the highest velocity
639+
left = math.sqrt(U_left**2 + V_left**2)
640+
right = math.sqrt(U_right**2 + V_right**2)
641+
up = math.sqrt(U_up**2 + V_up**2)
642+
down = math.sqrt(U_down**2 + V_down**2)
643+
644+
max_vel = 0.
645+
U_dir = 0.
646+
V_dir = 0.
647+
648+
if left + right + up + down > 1e-14:
649+
max_vel = left
650+
U_dir = -1.
651+
V_dir = 0.
652+
if max_vel < right:
653+
max_vel = right
654+
U_dir = 1.
655+
V_dir = 0.
656+
if max_vel < up:
657+
max_vel = up
658+
U_dir = 0.
659+
V_dir = 1.
660+
if max_vel < down:
661+
max_vel = down
662+
U_dir = 0.
663+
V_dir = -1.
664+
665+
# If all four cardinal directions are zero, check diagonal directions
666+
else:
667+
(U_left_up, V_left_up) = fieldset.UV[time, new_depth, new_lat + displacement, new_lon - displacement]
668+
(U_left_down, V_left_down) = fieldset.UV[time, new_depth, new_lat - displacement, new_lon - displacement]
669+
(U_right_up, V_right_up) = fieldset.UV[time, new_depth, new_lat + displacement, new_lon + displacement]
670+
(U_right_down, V_right_down) = fieldset.UV[time, new_depth, new_lat - displacement, new_lon + displacement]
671+
672+
left_up = math.sqrt(U_left_up**2 + V_left_up**2)
673+
left_down = math.sqrt(U_left_down**2 + V_left_down**2)
674+
right_up = math.sqrt(U_right_up**2 + V_right_up**2)
675+
right_down = math.sqrt(U_right_down**2 + V_right_down**2)
676+
677+
max_vel = left_up
678+
U_dir = -1.
679+
V_dir = 1.
680+
if max_vel < left_down:
681+
max_vel = left_down
682+
U_dir = 1.
683+
V_dir = -1.
684+
if max_vel < right_up:
685+
max_vel = right_up
686+
U_dir = 1.
687+
V_dir = 1.
688+
if max_vel < right_down:
689+
max_vel = right_down
690+
U_dir = 1.
691+
V_dir = -1.
692+
693+
particle_dlon += U_dir * unbeach_U * particle.dt
694+
particle_dlat += V_dir * unbeach_V * particle.dt
695+
598696

599697
def checkThroughBathymetry(particle, fieldset, time):
600698
"""Bathymetry error kernel.
@@ -629,6 +727,7 @@ def checkThroughBathymetry(particle, fieldset, time):
629727
elif potential_depth > 3900.: # If particle >3.9km deep, stick it there
630728
particle_ddepth = 3900. - particle.depth # noqa
631729

730+
632731
def reflectAtBathymetry(particle, fieldset, time):
633732
"""Reflect at bathymetry kernel.
634733

0 commit comments

Comments
 (0)