Repository: OceanParcels/parcels
Pull request #629 (2019-08-21 08:30:58)

Removing support for adding Particles via ParticleSet.add()
Since adding `Particles` directly to a `ParticleSet` breaks the `ParticleID` in MPI mode, for now we only support adding of `ParticleSets` to `ParticleSets`. 

Note that it is very easy to create a ParticleSet out of a single `Particle`, so this doesn’t fundamentally change Parcels capabilities.


Patch:
diff --git a/parcels/particleset.py b/parcels/particleset.py
index d06e4722..9ae27bc0 100644
--- a/parcels/particleset.py
+++ b/parcels/particleset.py
@@ -49,7 +49,7 @@ class ParticleSet(object):
             # Convert lists and single integers/floats to one-dimensional numpy arrays
             if isinstance(var, np.ndarray):
                 return var.flatten()
-            elif isinstance(var, (int, float)):
+            elif isinstance(var, (int, float, np.float32, np.int32)):
                 return np.array([var])
             else:
                 return np.array(var)
@@ -298,8 +298,8 @@ class ParticleSet(object):
         """Method to add particles to the ParticleSet"""
         if isinstance(particles, ParticleSet):
             particles = particles.particles
-        if not isinstance(particles, collections.Iterable):
-            particles = [particles]
+        else:
+            raise NotImplementedError('Only ParticleSets can be added to a ParticleSet')
         self.particles = np.append(self.particles, particles)
         if self.ptype.uses_jit:
             particles_data = [p._cptr for p in particles]


Test patch:
diff --git a/tests/test_particle_sets.py b/tests/test_particle_sets.py
index 8e43f52b..e38e2de3 100644
--- a/tests/test_particle_sets.py
+++ b/tests/test_particle_sets.py
@@ -187,7 +187,8 @@ def test_pset_add_explicit(fieldset, mode, npart=100):
     lat = np.linspace(1, 0, npart)
     pset = ParticleSet(fieldset, lon=[], lat=[], pclass=ptype[mode], lonlatdepth_dtype=np.float64)
     for i in range(npart):
-        particle = ptype[mode](lon=lon[i], lat=lat[i], fieldset=fieldset)
+        particle = ParticleSet(pclass=ptype[mode], lon=lon[i], lat=lat[i],
+                               fieldset=fieldset, lonlatdepth_dtype=np.float64)
         pset.add(particle)
     assert(pset.size == 100)
     assert np.allclose([p.lon for p in pset], lon, rtol=1e-12)
@@ -200,7 +201,7 @@ def test_pset_add_shorthand(fieldset, mode, npart=100):
     lat = np.linspace(1, 0, npart, dtype=np.float32)
     pset = ParticleSet(fieldset, lon=[], lat=[], pclass=ptype[mode])
     for i in range(npart):
-        pset += ptype[mode](lon=lon[i], lat=lat[i], fieldset=fieldset)
+        pset += ParticleSet(pclass=ptype[mode], lon=lon[i], lat=lat[i], fieldset=fieldset)
     assert(pset.size == 100)
     assert np.allclose([p.lon for p in pset], lon, rtol=1e-12)
     assert np.allclose([p.lat for p in pset], lat, rtol=1e-12)
@@ -213,7 +214,7 @@ def test_pset_add_execute(fieldset, mode, npart=10):
 
     pset = ParticleSet(fieldset, lon=[], lat=[], pclass=ptype[mode])
     for i in range(npart):
-        pset += ptype[mode](lon=0.1, lat=0.1, fieldset=fieldset)
+        pset += ParticleSet(pclass=ptype[mode], lon=0.1, lat=0.1, fieldset=fieldset)
     for _ in range(3):
         pset.execute(pset.Kernel(AddLat), runtime=1., dt=1.0)
     assert np.allclose(np.array([p.lat for p in pset]), 0.4, rtol=1e-12)
diff --git a/tests/test_scripts.py b/tests/test_scripts.py
index ff5d9acf..64fef3f5 100644
--- a/tests/test_scripts.py
+++ b/tests/test_scripts.py
@@ -25,7 +25,7 @@ def create_outputfiles(dir):
 
     for t in range(npart):
         time = 0 if len(pset) == 0 else pset[0].time
-        pset.add(JITParticle(lon=x, lat=lat[t], fieldset=fieldset, time=time))
+        pset.add(ParticleSet(pclass=JITParticle, lon=x, lat=lat[t], fieldset=fieldset, time=time))
         pset.execute(AdvectionRK4, runtime=delaytime, dt=delta(minutes=5),
                      output_file=output_file)