diff --git src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleCollector/ParticleCollector.C src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleCollector/ParticleCollector.C
index 3f278e8..f3e3fad 100644
--- src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleCollector/ParticleCollector.C
+++ src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleCollector/ParticleCollector.C
@@ -290,9 +290,6 @@ void Foam::ParticleCollector<CloudType>::collectParcelPolygon
     const point& p2
 ) const
 {
-    label dummyNearType = -1;
-    label dummyNearLabel = -1;
-
     forAll(faces_, facei)
     {
         const label facePoint0 = faces_[facei][0];
@@ -311,26 +308,31 @@ void Foam::ParticleCollector<CloudType>::collectParcelPolygon
         // Intersection point
         const point pIntersect = p1 + (d1/(d1 - d2))*(p2 - p1);
 
-        const List<face>& tris = faceTris_[facei];
-
-        // Identify if point is within poly bounds
-        forAll(tris, triI)
-        {
-            const face& tri = tris[triI];
-            triPointRef t
-            (
-                points_[tri[0]],
-                points_[tri[1]],
-                points_[tri[2]]
-            );
+        // Identify if point is within the bounds of the face. Create triangles
+        // between the intersection point and each edge of the face. If all the
+        // triangle normals point in the same direction as the face normal, then
+        // the particle is within the face. Note that testing the decomposed
+        // triangles in turn does not work due to ambiguity along the diagonals.
+        const face& f = faces_[facei];
+        const vector n = f.normal(points_);
+        bool inside = true;
+        for (label i = 0; i < f.size(); ++ i)
+        {
+            const label j = f.fcIndex(i);
+            const triPointRef t(pIntersect, points_[f[i]], points_[f[j]]);
+            if ((n & t.normal()) < 0)
+            {
+                inside = false;
+                break;
+            }
+        }
 
-            if (t.classify(pIntersect, dummyNearType, dummyNearLabel))
+        if (inside)
         {
             hitFaceIDs_.append(facei);
         }
     }
 }
-}
 
 
 template<class CloudType>
@@ -505,7 +507,10 @@ void Foam::ParticleCollector<CloudType>::write()
         mass_[facei] = 0.0;
         massTotal_[facei] = 0.0;
         massFlowRate_[facei] = 0.0;
+        collectedParticles0_[facei] = collectedParticles_[facei];
+        collectedParticles_[facei].clear();
     }
+
 }
 
 
@@ -543,7 +548,9 @@ Foam::ParticleCollector<CloudType>::ParticleCollector
     log_(this->coeffDict().lookup("log")),
     outputFilePtr_(),
     timeOld_(owner.mesh().time().value()),
-    hitFaceIDs_()
+    hitFaceIDs_(),
+    collectedParticles_(),
+    collectedParticles0_()
 {
     normal_ /= mag(normal_);
 
@@ -594,6 +601,8 @@ Foam::ParticleCollector<CloudType>::ParticleCollector
     mass_.setSize(faces_.size(), 0.0);
     massTotal_.setSize(faces_.size(), 0.0);
     massFlowRate_.setSize(faces_.size(), 0.0);
+    collectedParticles_.setSize(faces_.size());
+    collectedParticles0_.setSize(faces_.size());
 
     makeLogFile(faces_, points_, area_);
 }
@@ -626,7 +635,9 @@ Foam::ParticleCollector<CloudType>::ParticleCollector
     log_(pc.log_),
     outputFilePtr_(),
     timeOld_(0.0),
-    hitFaceIDs_()
+    hitFaceIDs_(),
+    collectedParticles_(pc.collectedParticles_),
+    collectedParticles0_(pc.collectedParticles0_)
 {}
 
 
@@ -675,7 +686,6 @@ void Foam::ParticleCollector<CloudType>::postMove
         {}
     }
 
-
     forAll(hitFaceIDs_, i)
     {
         label facei = hitFaceIDs_[i];
@@ -709,9 +719,29 @@ void Foam::ParticleCollector<CloudType>::postMove
             }
         }
 
-        // Add mass contribution
-        mass_[facei] += m;
+        // If not previously collected, add mass contribution
+        Switch previouslyCollected = false;
+        forAll(collectedParticles0_[facei],i)
+        {
+            if (&p == collectedParticles0_[facei][i] )
+            {
+                previouslyCollected = true;
+                break;
+            }
+        }
+        forAll(collectedParticles_[facei],i)
+        {
+            if (&p == collectedParticles_[facei][i] )
+            {
+                previouslyCollected = true;
+                break;
+            }
+        }
+        if(!previouslyCollected)
+        {
+            collectedParticles_[facei].append(&p);
 
+            mass_[facei] += m;
             if (nSector_ == 1)
             {
                 mass_[facei + 1] += m;
@@ -725,6 +755,7 @@ void Foam::ParticleCollector<CloudType>::postMove
             }
         }
     }
+}
 
 
 // ************************************************************************* //
diff --git src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleCollector/ParticleCollector.H src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleCollector/ParticleCollector.H
index d14195a..ebe1512 100644
--- src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleCollector/ParticleCollector.H
+++ src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleCollector/ParticleCollector.H
@@ -200,6 +200,12 @@ private:
         //- Work list to store which faces are hit
         mutable DynamicList<label> hitFaceIDs_;
 
+        //- Work list to store which particles are collected at current time step
+        List<DynamicList<typename CloudType::parcelType*>> collectedParticles_;
+
+        //- Work list to store which particles are collected at previous time step
+        List<DynamicList<typename CloudType::parcelType*>> collectedParticles0_;
+
 
     // Private Member Functions
 
