Commit c9b37446 authored by Will Bainbridge's avatar Will Bainbridge Committed by Andrew Heather
Browse files

ParticleCollector: Prevented missing and duplicate collections

The particle collector was collecting some particles twice due to a
tolerance extending the tracked path. This has been removed. The new
tracking algorithm does not generate the same sorts of spurious
tolerance-scale motions that the old one did, so this extension of the
tracking path is unnecessary.

Some particles were also not being collected at all as they were hitting
a diagonal of the collection polygon and registering as not having hit
either of the adjacent triangles. The hit criteria has been rewritten. A
hit now occurs when the normals of the triangles created by joining the
intersection point with the polygon edges are all in the same direction
as the overall polygon normal. This calculation is not affected by the
polygon's diagonals.

The issue was raised by, and resolved with support from, Karl Meredith
at FM Global.

This resolves bug-report
parent 6b316ba3
......@@ -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,24 +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)
// 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 for pointHits on
// the face's decomposed triangles 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 face& tri = tris[triI];
triPointRef t
if (t.classify(pIntersect, dummyNearType, dummyNearLabel))
const label j = f.fcIndex(i);
const triPointRef t(pIntersect, points_[f[i]], points_[f[j]]);
if ((n & t.normal()) < 0)
inside = false;
// Add to the list of hits
if (inside)
......@@ -660,28 +664,24 @@ void Foam::ParticleCollector<CloudType>::postMove
// Slightly extend end position to avoid falling within tracking tolerances
const point position1 = position0 + 1.0001*(p.position() - position0);
switch (mode_)
case mtPolygon:
collectParcelPolygon(position0, position1);
collectParcelPolygon(position0, p.position());
case mtConcentricCircle:
collectParcelConcentricCircles(position0, position1);
collectParcelConcentricCircles(position0, p.position());
forAll(hitFaceIDs_, i)
label facei = hitFaceIDs_[i];
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment