From 36640eee65b91dcbd60f8777566ddc309b485d01 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Fri, 18 Jul 2025 07:29:37 +0200 Subject: [PATCH 1/4] Performance boost by particle.__setattr__ to call numpy data directly --- parcels/particle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parcels/particle.py b/parcels/particle.py index 93ea35254..142de7d5f 100644 --- a/parcels/particle.py +++ b/parcels/particle.py @@ -121,7 +121,7 @@ def __setattr__(self, name, value): if name in ["_data", "_index"]: object.__setattr__(self, name, value) else: - self._data[name][self._index] = value + self._data[name].data[self._index] = value def delete(self): """Signal the particle for deletion.""" From 420ca9e1df3fa3c4666c11d342bf5ecb4feee11c Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Fri, 18 Jul 2025 09:05:22 +0200 Subject: [PATCH 2/4] Only calling remove-indices when there are particles to be removed --- parcels/kernel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parcels/kernel.py b/parcels/kernel.py index 4b55a7634..911c890bd 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -75,7 +75,8 @@ def remove_deleted(self, pset): # TODO v4: need to implement ParticleFile writing of deleted particles # if len(indices) > 0 and self.fieldset.particlefile is not None: # self.fieldset.particlefile.write(pset, None, indices=indices) - pset.remove_indices(indices) + if len(indices) > 0: + pset.remove_indices(indices) class Kernel(BaseKernel): From 33102d48f9114f8f7e90a6d65109d6b993ed303d Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Fri, 18 Jul 2025 09:55:02 +0200 Subject: [PATCH 3/4] Fixing unit test --- tests/v4/test_particleset_execute.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/v4/test_particleset_execute.py b/tests/v4/test_particleset_execute.py index fe97546a3..022377029 100644 --- a/tests/v4/test_particleset_execute.py +++ b/tests/v4/test_particleset_execute.py @@ -112,8 +112,7 @@ def PythonFail(particle, fieldset, time): # pragma: no cover with pytest.raises(RuntimeError): pset.execute(PythonFail, runtime=np.timedelta64(20, "s"), dt=np.timedelta64(2, "s")) assert len(pset) == npart - assert pset.time[0] == fieldset.time_interval.left + np.timedelta64(10, "s") - assert all([time == fieldset.time_interval.left + np.timedelta64(8, "s") for time in pset.time[1:]]) + assert all([time == fieldset.time_interval.left + np.timedelta64(10, "s") for time in pset.time]) @pytest.mark.parametrize("verbose_progress", [True, False]) From ef027de412526bfc7a3356c1b13d4a5065ceccc4 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Fri, 18 Jul 2025 13:22:44 +0200 Subject: [PATCH 4/4] Also directly accessing numpy array in Particle.__getattr__ Although this does not appear to result in a speed-up --- parcels/particle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parcels/particle.py b/parcels/particle.py index 142de7d5f..a72886f5f 100644 --- a/parcels/particle.py +++ b/parcels/particle.py @@ -115,7 +115,7 @@ def __init__(self, data: xr.Dataset, index: int): self._index = index def __getattr__(self, name): - return self._data[name].values[self._index] + return self._data[name].data[self._index] def __setattr__(self, name, value): if name in ["_data", "_index"]: