From e6b0ea7151ac7835889ca18b4ccb8af7870888af Mon Sep 17 00:00:00 2001 From: Wyatt Sieminski Date: Wed, 29 Jul 2026 12:18:34 -0400 Subject: [PATCH 1/5] Modified logic for setting the default z value for particles --- src/parcels/_core/particleset.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/parcels/_core/particleset.py b/src/parcels/_core/particleset.py index 6f65d53e0..2dea21226 100644 --- a/src/parcels/_core/particleset.py +++ b/src/parcels/_core/particleset.py @@ -78,11 +78,15 @@ def __init__( particle_ids = np.arange(x.size) if z is None: - minz = 0 + minz = None for field in self.fieldset.fields.values(): - if field.grid.depth is not None: - minz = min(minz, field.grid.depth[0]) - z = np.ones(x.size) * minz + for depth in field.grid.depth: + if minz is None or np.abs(depth) < np.abs(minz): + minz = depth + if minz is not None: + z = np.ones(x.size) * minz + else: + z = np.zeros(x.size) else: z = np.array(z).flatten() assert x.size == y.size and x.size == z.size, "x, y, z don't all have the same lengths" From 53318335e24c8e278a369ec12c9c7c2288fb9855 Mon Sep 17 00:00:00 2001 From: Wyatt Sieminski Date: Tue, 4 Aug 2026 19:21:38 +0000 Subject: [PATCH 2/5] Added testing for default z position. --- tests/test_particleset.py | 43 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/test_particleset.py b/tests/test_particleset.py index c8211baf9..30d23ffeb 100644 --- a/tests/test_particleset.py +++ b/tests/test_particleset.py @@ -7,6 +7,7 @@ import xarray as xr from parcels import ( + FieldSet, Particle, ParticleSet, ParticleSetWarning, @@ -14,7 +15,7 @@ ) from tests.common_kernels import DoNothing from tests.utils import round_and_hash_float_array - +from parcels._datasets.structured.generated import simple_UV_dataset def test_pset_create_lon_lat(fieldset): npart = 100 @@ -174,3 +175,43 @@ def test_pset_iterator(fieldset): for i, particle in enumerate(pset): assert particle.particle_id == i assert i == npart - 1 + +@pytest.mark.parametrize( + "depths", + [ + pytest.param(np.linspace(1, 10, 10), id="all_depths_positive"), + pytest.param(np.linspace(-10, -1, 10), id="all_depths_negative"), + ], +) +def test_pset_default_z_is_in_domain(depths): + ds = simple_UV_dataset(dims=(1, len(depths), 10, 10), mesh="flat") + ds = ds.assign_coords(depth=depths) + fieldset = FieldSet.from_sgrid_conventions(ds, mesh="flat") + + pset = ParticleSet(fieldset, x=[0], y=[0]) + expected_z = depths[np.argmin(np.abs(depths))] + assert np.isclose(pset.z[0], expected_z) + + +@pytest.mark.parametrize( + "depths", + [ + pytest.param( + np.concatenate([np.linspace(-15, -1, 5), np.linspace(0, 2, 5)]), id="depths_include_zero" + ), + pytest.param( + np.concatenate([np.linspace(-9, -3, 3), np.linspace(2, 8, 3)]), id="closest_depth_is_positive" + ), + pytest.param( + np.concatenate([np.linspace(-8, -2, 3), np.linspace(3, 9, 3)]), id="closest_depth_is_negative" + ), + ], +) +def test_pset_default_z_closest_to_zero(depths): + ds = simple_UV_dataset(dims=(1, len(depths), 10, 10), mesh="flat") + ds = ds.assign_coords(depth=depths) + fieldset = FieldSet.from_sgrid_conventions(ds, mesh="flat") + + pset = ParticleSet(fieldset, x=[0], y=[0]) + expected_z = depths[np.argmin(np.abs(depths))] + assert np.isclose(pset.z[0], expected_z) From 53e258b8531b0506bb620c1a95a7694a86cebb4b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 19:21:55 +0000 Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_particleset.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/test_particleset.py b/tests/test_particleset.py index 30d23ffeb..4e3ce9dc5 100644 --- a/tests/test_particleset.py +++ b/tests/test_particleset.py @@ -13,9 +13,10 @@ ParticleSetWarning, Variable, ) +from parcels._datasets.structured.generated import simple_UV_dataset from tests.common_kernels import DoNothing from tests.utils import round_and_hash_float_array -from parcels._datasets.structured.generated import simple_UV_dataset + def test_pset_create_lon_lat(fieldset): npart = 100 @@ -176,6 +177,7 @@ def test_pset_iterator(fieldset): assert particle.particle_id == i assert i == npart - 1 + @pytest.mark.parametrize( "depths", [ @@ -196,15 +198,9 @@ def test_pset_default_z_is_in_domain(depths): @pytest.mark.parametrize( "depths", [ - pytest.param( - np.concatenate([np.linspace(-15, -1, 5), np.linspace(0, 2, 5)]), id="depths_include_zero" - ), - pytest.param( - np.concatenate([np.linspace(-9, -3, 3), np.linspace(2, 8, 3)]), id="closest_depth_is_positive" - ), - pytest.param( - np.concatenate([np.linspace(-8, -2, 3), np.linspace(3, 9, 3)]), id="closest_depth_is_negative" - ), + pytest.param(np.concatenate([np.linspace(-15, -1, 5), np.linspace(0, 2, 5)]), id="depths_include_zero"), + pytest.param(np.concatenate([np.linspace(-9, -3, 3), np.linspace(2, 8, 3)]), id="closest_depth_is_positive"), + pytest.param(np.concatenate([np.linspace(-8, -2, 3), np.linspace(3, 9, 3)]), id="closest_depth_is_negative"), ], ) def test_pset_default_z_closest_to_zero(depths): From f36e2de9736f9434d889844ad189f8e604a33611 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Wed, 5 Aug 2026 08:05:56 +0200 Subject: [PATCH 4/5] Updating docstring for default z --- src/parcels/_core/particleset.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parcels/_core/particleset.py b/src/parcels/_core/particleset.py index 2dea21226..0b171366d 100644 --- a/src/parcels/_core/particleset.py +++ b/src/parcels/_core/particleset.py @@ -44,7 +44,8 @@ class ParticleSet: y : List of initial y (latitude) values for particles z : - Optional list of initial z values for particles. Default is 0m + Optional list of initial z values for particles. Default is vertical grid position closest to the surface (z=0) + that covers all fields in the fieldset. t : Optional list of initial t (time) values for particles. Default is fieldset.U.grid.time[0] repeatdt : datetime.timedelta or float, optional From ce50e41cad173e1d1f9e0222f8acabf100ac6605 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Wed, 5 Aug 2026 08:07:33 +0200 Subject: [PATCH 5/5] Further update to the docstring --- src/parcels/_core/particleset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parcels/_core/particleset.py b/src/parcels/_core/particleset.py index 0b171366d..3b5ecf2aa 100644 --- a/src/parcels/_core/particleset.py +++ b/src/parcels/_core/particleset.py @@ -45,7 +45,7 @@ class ParticleSet: List of initial y (latitude) values for particles z : Optional list of initial z values for particles. Default is vertical grid position closest to the surface (z=0) - that covers all fields in the fieldset. + that covers all fields in the fieldset. If none of the fields in the fieldset have a vertical grid, z=0 is used. t : Optional list of initial t (time) values for particles. Default is fieldset.U.grid.time[0] repeatdt : datetime.timedelta or float, optional