Skip to content

Commit 9027987

Browse files
Using helper function to adjust dt
1 parent 2275ccb commit 9027987

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

src/parcels/kernels/advection.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,17 @@
1818
]
1919

2020

21+
def _adjust_RK_dt(time_interval, time, dt):
22+
"""Helper function to make sure dt does not go outside time_interval for RK methods"""
23+
if time_interval:
24+
dt = np.where(time + dt <= time_interval.right, dt, time_interval.right - time)
25+
dt = np.where(time + dt >= time_interval.left, dt, time - time_interval.left)
26+
return dt
27+
28+
2129
def AdvectionRK2(particles, fieldset): # pragma: no cover
2230
"""Advection of particles using second-order Runge-Kutta integration."""
31+
particles.dt = _adjust_RK_dt(fieldset.time_interval, particles.time, particles.dt)
2332
dt = particles.dt / np.timedelta64(1, "s") # TODO: improve API for converting dt to seconds
2433
(u1, v1) = fieldset.UV[particles]
2534
lon1, lat1 = (particles.lon + u1 * 0.5 * dt, particles.lat + v1 * 0.5 * dt)
@@ -30,6 +39,7 @@ def AdvectionRK2(particles, fieldset): # pragma: no cover
3039

3140
def AdvectionRK2_3D(particles, fieldset): # pragma: no cover
3241
"""Advection of particles using second-order Runge-Kutta integration including vertical velocity."""
42+
particles.dt = _adjust_RK_dt(fieldset.time_interval, particles.time, particles.dt)
3343
dt = particles.dt / np.timedelta64(1, "s")
3444
(u1, v1, w1) = fieldset.UVW[particles]
3545
lon1 = particles.lon + u1 * 0.5 * dt
@@ -43,32 +53,22 @@ def AdvectionRK2_3D(particles, fieldset): # pragma: no cover
4353

4454
def AdvectionRK4(particles, fieldset): # pragma: no cover
4555
"""Advection of particles using fourth-order Runge-Kutta integration."""
46-
47-
def Update_locations(p):
48-
dt = p.dt / np.timedelta64(1, "s") # TODO: improve API for converting dt to seconds
49-
(u1, v1) = fieldset.UV[p]
50-
lon1, lat1 = (p.lon + u1 * 0.5 * dt, p.lat + v1 * 0.5 * dt)
51-
(u2, v2) = fieldset.UV[p.time + 0.5 * p.dt, p.z, lat1, lon1, p]
52-
lon2, lat2 = (p.lon + u2 * 0.5 * dt, p.lat + v2 * 0.5 * dt)
53-
(u3, v3) = fieldset.UV[p.time + 0.5 * p.dt, p.z, lat2, lon2, p]
54-
lon3, lat3 = (p.lon + u3 * dt, p.lat + v3 * dt)
55-
(u4, v4) = fieldset.UV[p.time + p.dt, p.z, lat3, lon3, p]
56-
p.dlon += (u1 + 2 * u2 + 2 * u3 + u4) / 6.0 * dt
57-
p.dlat += (v1 + 2 * v2 + 2 * v3 + v4) / 6.0 * dt
58-
59-
if fieldset.time_interval is not None:
60-
Update_locations(
61-
particles[
62-
(particles.time + particles.dt <= fieldset.time_interval.right)
63-
& (particles.time + particles.dt >= fieldset.time_interval.left)
64-
]
65-
)
66-
else:
67-
Update_locations(particles)
56+
particles.dt = _adjust_RK_dt(fieldset.time_interval, particles.time, particles.dt)
57+
dt = particles.dt / np.timedelta64(1, "s") # TODO: improve API for converting dt to seconds
58+
(u1, v1) = fieldset.UV[particles]
59+
lon1, lat1 = (particles.lon + u1 * 0.5 * dt, particles.lat + v1 * 0.5 * dt)
60+
(u2, v2) = fieldset.UV[particles.time + 0.5 * particles.dt, particles.z, lat1, lon1, particles]
61+
lon2, lat2 = (particles.lon + u2 * 0.5 * dt, particles.lat + v2 * 0.5 * dt)
62+
(u3, v3) = fieldset.UV[particles.time + 0.5 * particles.dt, particles.z, lat2, lon2, particles]
63+
lon3, lat3 = (particles.lon + u3 * dt, particles.lat + v3 * dt)
64+
(u4, v4) = fieldset.UV[particles.time + particles.dt, particles.z, lat3, lon3, particles]
65+
particles.dlon += (u1 + 2 * u2 + 2 * u3 + u4) / 6.0 * dt
66+
particles.dlat += (v1 + 2 * v2 + 2 * v3 + v4) / 6.0 * dt
6867

6968

7069
def AdvectionRK4_3D(particles, fieldset): # pragma: no cover
7170
"""Advection of particles using fourth-order Runge-Kutta integration including vertical velocity."""
71+
particles.dt = _adjust_RK_dt(fieldset.time_interval, particles.time, particles.dt)
7272
dt = particles.dt / np.timedelta64(1, "s")
7373
(u1, v1, w1) = fieldset.UVW[particles]
7474
lon1 = particles.lon + u1 * 0.5 * dt
@@ -92,6 +92,7 @@ def AdvectionRK4_3D_CROCO(particles, fieldset): # pragma: no cover
9292
"""Advection of particles using fourth-order Runge-Kutta integration including vertical velocity.
9393
This kernel assumes the vertical velocity is the 'w' field from CROCO output and works on sigma-layers.
9494
"""
95+
particles.dt = _adjust_RK_dt(fieldset.time_interval, particles.time, particles.dt)
9596
dt = particles.dt / np.timedelta64(1, "s") # TODO: improve API for converting dt to seconds
9697
sig_dep = particles.z / fieldset.H[particles.time, 0, particles.lat, particles.lon]
9798

@@ -148,6 +149,7 @@ def AdvectionRK45(particles, fieldset): # pragma: no cover
148149
Time-step dt is halved if error is larger than fieldset.RK45_tol,
149150
and doubled if error is smaller than 1/10th of tolerance.
150151
"""
152+
particles.dt = _adjust_RK_dt(fieldset.time_interval, particles.time, particles.dt)
151153
dt = particles.dt / np.timedelta64(1, "s") # TODO: improve API for converting dt to seconds
152154

153155
c = [1.0 / 4.0, 3.0 / 8.0, 12.0 / 13.0, 1.0, 1.0 / 2.0]

0 commit comments

Comments
 (0)