Trying various methods to decide what to do. Best guess of which cell

the particle is in is off, going to try a different way.
This commit is contained in:
graham
2009-10-09 16:36:11 +01:00
parent 5488acac27
commit 20ab51ca50
3 changed files with 263 additions and 139 deletions

View File

@ -42,7 +42,7 @@ template<class ParticleType>
const Foam::scalar Foam::Cloud<ParticleType>::trackingRescueTolerance = 1e-6; const Foam::scalar Foam::Cloud<ParticleType>::trackingRescueTolerance = 1e-6;
template<class ParticleType> template<class ParticleType>
const Foam::scalar Foam::Cloud<ParticleType>::intersectionTolerance = SMALL; const Foam::scalar Foam::Cloud<ParticleType>::intersectionTolerance = 0;
template<class ParticleType> template<class ParticleType>
const Foam::scalar Foam::Cloud<ParticleType>::planarCosAngle = (1 - 1e-6); const Foam::scalar Foam::Cloud<ParticleType>::planarCosAngle = (1 - 1e-6);

View File

@ -89,53 +89,30 @@ void Foam::Particle<ParticleType>::findFaces
template<class ParticleType> template<class ParticleType>
template<class TrackData> bool Foam::Particle<ParticleType>::insideCellExact
void Foam::Particle<ParticleType>::trackToFaceConcave
( (
scalar& trackFraction, const vector& testPt,
const vector& endPosition, const label celli,
TrackData& td bool includeOnFace
) ) const
{ {
facei_ = -1;
const polyMesh& mesh = cloud_.pMesh(); const polyMesh& mesh = cloud_.pMesh();
const labelList& faces = mesh.cells()[celli_]; const labelList& faces = mesh.cells()[celli];
const vector& C = mesh.cellCentres()[celli_]; const vector& C = mesh.cellCentres()[celli];
DynamicList<label>& potentiallyCrossedFaces = cloud_.labels_;
findFaces(endPosition, potentiallyCrossedFaces);
// Check all possible face crossings to see if they are actually
// crossed, determining if endPosition is outside the current cell.
if (potentiallyCrossedFaces.empty())
{
// endPosition is inside the cell
position_ = endPosition;
trackFraction = 1.0;
return;
}
Pout<< nl << origProc_ << " "
<< origId_ << " "
<< position_ << " "
<< endPosition << " "
<< celli_ << nl
<< potentiallyCrossedFaces
<< endl;
label nFaceCrossings = 0; label nFaceCrossings = 0;
forAll (potentiallyCrossedFaces, pCFI) // The vector from the cell centre to the end point
vector delta = testPt - C;
forAll (faces, i)
{ {
label facei = potentiallyCrossedFaces[pCFI]; label facei = faces[i];
pointHit inter = mesh.faces()[facei].intersection pointHit inter = mesh.faces()[facei].intersection
( (
C, C,
endPosition - C, delta,
mesh.faceCentres()[facei], mesh.faceCentres()[facei],
mesh.points(), mesh.points(),
intersection::HALF_RAY, intersection::HALF_RAY,
@ -143,19 +120,26 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
); );
if (inter.hit()) if (inter.hit())
{
// Pout<< "insideCellExact " << facei << " "
// << inter.distance() << endl;
if (includeOnFace)
{
if (inter.distance() <= 1.0)
{
// This face was actually crossed.
nFaceCrossings++;
}
}
else
{ {
if (inter.distance() < 1.0) if (inter.distance() < 1.0)
{ {
// This face was actually crossed. // This face was actually crossed.
nFaceCrossings++; nFaceCrossings++;
if (inter.distance() < 0.0)
{
FatalErrorIn("Particle::trackToFaceConcave")
<< "Negative lambda " << inter.distance()
<< "in potentiallyCrossedFaces test"
<< nl << abort(FatalError);
} }
} }
} }
@ -169,9 +153,42 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
<< endl; << endl;
} }
Pout<< nFaceCrossings << " " << (nFaceCrossings % 2) << endl;
if (nFaceCrossings % 2 == 0) if (nFaceCrossings % 2 == 0)
{
// Even number of face crossings, so the testPt must be in the
// cell.
return true;
}
return false;
}
template<class ParticleType>
template<class TrackData>
void Foam::Particle<ParticleType>::trackToFaceConcave
(
scalar& trackFraction,
const vector& endPosition,
TrackData& td
)
{
facei_ = -1;
const polyMesh& mesh = cloud_.pMesh();
const labelList& faces = mesh.cells()[celli_];
// const vector& C = mesh.cellCentres()[celli_];
// Check all possible face crossings to see if they are actually
// crossed, determining if endPosition is outside the current
// cell. This allows situations where the cell is outside the
// cell to start with and enters the cell at the end of the track
// to be identified.
// Pout<< nl << "Outside test:" << endl;
if (insideCellExact(endPosition, celli_, false))
{ {
// Even number of face crossings, so the particle must end up // Even number of face crossings, so the particle must end up
// still in the cell. // still in the cell.
@ -181,11 +198,20 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
return; return;
} }
Pout<< nl << origProc_ << " "
<< origId_ << " "
<< position_ << " "
<< endPosition << " "
<< stepFraction_ << " "
<< celli_
<< endl;
// The particle *must* have left the cell. // The particle *must* have left the cell.
// a) It may have crossed a face not yet identified by findFaces using the // a) It may have crossed a face not yet identified by testing
// cell centre to endPosition line, so the potentially crossed faces of // faces using the cell centre to endPosition line, so the
// the position to endPosition line must be assessed. // potentially crossed faces of the position to endPosition
// line must be assessed.
// b) It may have been outside the cell in the first place, and, despite // b) It may have been outside the cell in the first place, and, despite
// trying to pick up more faces using a) the correct face to be crossed // trying to pick up more faces using a) the correct face to be crossed
@ -197,38 +223,28 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
// as nothing can be assumed about the order of crossing the // as nothing can be assumed about the order of crossing the
// planes of faces. // planes of faces.
forAll(faces, i) const vector deltaPosition = endPosition - position_;
{ vector deltaTrack =
label facei = faces[i]; mag(mesh.cellCentres()[celli_] - position_)
*deltaPosition/(mag(deltaPosition) + VSMALL);
scalar lam = lambda(position_, endPosition, facei); // Pout<< "Inside test:" << endl;
if ((lam > 0) && (lam < 1.0)) if (insideCellExact(position_, celli_, false))
{ {
if (findIndex(potentiallyCrossedFaces, facei) == -1) Pout<< "The particle starts inside the cell and ends up outside of it"
{ << nl << position_ << " " << position_ + deltaTrack
// A new potential face crossing, previously missed,
// has been found
Pout<< "New face crossing " << facei
<< " of concave cell " << celli_ << " found"
<< endl; << endl;
potentiallyCrossedFaces.append(facei); // The particle started inside the cell and finished outside
} // of it, find which face to cross
}
}
Pout<< potentiallyCrossedFaces << endl;
vector deltaPosition = endPosition - position_;
scalar tmpLambda = GREAT; scalar tmpLambda = GREAT;
scalar correctLambda = GREAT; scalar correctLambda = GREAT;
forAll(potentiallyCrossedFaces, pCFI) forAll(faces, i)
{ {
label facei = potentiallyCrossedFaces[pCFI]; label facei = faces[i];
// Use exact intersection. // Use exact intersection.
@ -249,9 +265,11 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
{ {
tmpLambda = inter.distance(); tmpLambda = inter.distance();
Pout<< facei << " " << tmpLambda << endl;
if if
( (
tmpLambda < 1.0 tmpLambda <= 1.0
&& tmpLambda < correctLambda && tmpLambda < correctLambda
) )
{ {
@ -266,27 +284,83 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
if (facei_ > -1) if (facei_ > -1)
{ {
if (!cloud_.internalFace(facei_))
{
label patchi = patch(facei_);
const polyPatch& patch = mesh.boundaryMesh()[patchi];
if (isA<wallPolyPatch>(patch))
{
if ((mesh.faceAreas()[facei_] & deltaPosition) <= 0)
{
// The particle has hit a wall face but it is
// heading in the wrong direction with respect to
// the face normal
// Do not trigger a face hit and move the position
// towards the cell centre
Pout<< "Hit a wall face heading the wrong way"
<< endl;
const point& cc = mesh.cellCentres()[celli_];
position_ += 1e-2*(cc - position_);
facei_ = -1;
}
}
}
else if (correctLambda < Cloud<ParticleType>::minValidTrackFraction)
{
// The particle is not far enough away from the face
// to decide if it is valid crossing. Let it move a
// little without crossing the face to resolve the
// ambiguity.
Pout<< "Ambiguous face crossing, correcting towards cell "
<< "centre and not crossing face" << endl;
const point& cc = mesh.cellCentres()[celli_];
position_ +=
Cloud<ParticleType>::trackingRescueTolerance
*(cc - position_);
// Pout<< "Ambiguous face crossing. " << endl;
// correctLambda += Cloud<ParticleType>::minValidTrackFraction;
facei_ = -1;
}
trackFraction = correctLambda; trackFraction = correctLambda;
position_ += trackFraction*(endPosition - position_); position_ += trackFraction*(endPosition - position_);
} }
else else
{ {
Pout<< "Particle " << origProc_ << " " << origId_
<< " started inside cell " << celli_ << " and finished outside"
<< " of it, but did not find a face to cross"
<< endl;
const point& cc = mesh.cellCentres()[celli_];
position_ += 1e-2*(cc - position_);
}
}
else
{
Pout<< "The particle started outside of the cell" << endl;
// No face has been identified to be crossed yet, but the cell // No face has been identified to be crossed yet, but the cell
// must have been left, so the best guess of which face to // must have been left, so the best guess of which face to
// cross is required. // cross is required.
vector delta =
mag(mesh.cellCentres()[celli_] - position_)
*deltaPosition/mag(deltaPosition);
Pout<< "Need a best guess " << nl Pout<< "Need a best guess " << nl
<< position_ << nl << position_ << nl
<< stepFraction_ << nl << stepFraction_ << nl
<< position_ + delta << nl << position_ + deltaTrack << nl
<< position_ - delta << position_ - deltaTrack
<< endl; << endl;
// ---- Best guess by projection -- // Best guess by projection
DynamicList<scalar> tmpLambdas; DynamicList<scalar> tmpLambdas;
DynamicList<label> tmpLambdaFaceIs; DynamicList<label> tmpLambdaFaceIs;
@ -320,11 +394,45 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
Pout<< tmpLambdaFaceIs << " " << tmpLambdas << endl; Pout<< tmpLambdaFaceIs << " " << tmpLambdas << endl;
scalar closestLambda = GREAT;
label closestLambdaFaceI = -1;
// Is there a face crossing that has been missed?
forAll(tmpLambdaFaceIs, i)
{
label facei = tmpLambdaFaceIs[i];
scalar tmpLambda = tmpLambdas[i];
if (!cloud_.internalFace(facei))
{
// Boundary faces trump internal faces
closestLambda = tmpLambda;
closestLambdaFaceI = facei;
break;
}
else if
(
tmpLambda >= 0.0
&& tmpLambda <= 1.0
&& tmpLambda < closestLambda
)
{
closestLambda = tmpLambda;
closestLambdaFaceI = facei;
}
}
// Find the closest lambda by projection.
if (closestLambdaFaceI == -1)
{
Pout<< "Test by projection" << endl;
// The closest lambda value (less than zero) or (greater than or // The closest lambda value (less than zero) or (greater than or
// equal to one), and corresponding face. // equal to one), and corresponding face.
scalar closestLambda = GREAT;
scalar closestLambdaDifference = GREAT; // Limit how far away from the track a projected face can be
label closestLambdaDifferenceFaceI = -1; scalar closestLambdaDifference = 100.0;
forAll(tmpLambdaFaceIs, i) forAll(tmpLambdaFaceIs, i)
{ {
@ -337,7 +445,7 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
{ {
closestLambdaDifference = mag(tmpLambda); closestLambdaDifference = mag(tmpLambda);
closestLambda = tmpLambda; closestLambda = tmpLambda;
closestLambdaDifferenceFaceI = facei; closestLambdaFaceI = facei;
} }
} }
else if (tmpLambda >= 1.0) else if (tmpLambda >= 1.0)
@ -346,12 +454,13 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
{ {
closestLambdaDifference = tmpLambda - 1.0; closestLambdaDifference = tmpLambda - 1.0;
closestLambda = tmpLambda; closestLambda = tmpLambda;
closestLambdaDifferenceFaceI = facei; closestLambdaFaceI = facei;
}
} }
} }
} }
if (closestLambdaDifferenceFaceI > -1) if (closestLambdaFaceI > -1)
{ {
// A face has been found to cross. Not moving the // A face has been found to cross. Not moving the
// particle at all, but the option is there to decide do // particle at all, but the option is there to decide do
@ -359,7 +468,10 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
// if the particle is heading towards, or away from the // if the particle is heading towards, or away from the
// face. // face.
facei_ = closestLambdaDifferenceFaceI; facei_ = closestLambdaFaceI;
trackFraction = Cloud<ParticleType>::minValidTrackFraction;
position_ += trackFraction*(endPosition - position_);
} }
else else
{ {
@ -373,7 +485,6 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
<< celli_ << " " << celli_ << " "
<< endl; << endl;
// ---- Best guess by nearest ----
scalar minDistance = GREAT; scalar minDistance = GREAT;
forAll(faces, i) forAll(faces, i)
@ -396,13 +507,17 @@ void Foam::Particle<ParticleType>::trackToFaceConcave
} }
} }
// ---- End of best guess by nearest ---- trackFraction = Cloud<ParticleType>::minValidTrackFraction;
position_ += trackFraction*(endPosition - position_);
} }
} }
Pout<< facei_ << " " << celli_ << endl; Pout<< facei_ << " " << celli_ << endl;
if (facei_ > -1)
{
faceAction(trackFraction, endPosition, td); faceAction(trackFraction, endPosition, td);
}
Pout<< facei_ << " " << celli_ << endl; Pout<< facei_ << " " << celli_ << endl;
} }

View File

@ -173,6 +173,15 @@ protected:
DynamicList<label>& faceList DynamicList<label>& faceList
) const; ) const;
//- Determine if the testPt is inside the cell by an exact
// intersection test
bool insideCellExact
(
const vector& testPt,
const label celli,
bool includeOnFace
) const;
//- Track to cell face using face decomposition, used for //- Track to cell face using face decomposition, used for
// concave cells. // concave cells.
template<class TrackData> template<class TrackData>