ENH: Updating particle member functions

- Dealing with detA < 0 tracking issues
- Modified locate function
This commit is contained in:
Sergio Ferraris
2020-08-28 08:19:06 -07:00
committed by Andrew Heather
parent 8427eccd00
commit f7dc0d8edb
4 changed files with 278 additions and 103 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd. Copyright (C) 2018-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -40,7 +40,7 @@ namespace Foam
defineTypeNameAndDebug(particle, 0); defineTypeNameAndDebug(particle, 0);
} }
const Foam::scalar Foam::particle::negativeSpaceDisplacementFactor = 1.01; const Foam::label Foam::particle::maxNBehind_ = 10;
Foam::label Foam::particle::particleCount_ = 0; Foam::label Foam::particle::particleCount_ = 0;
@ -365,7 +365,6 @@ void Foam::particle::changeCell()
const label ownerCellI = mesh_.faceOwner()[tetFacei_]; const label ownerCellI = mesh_.faceOwner()[tetFacei_];
const bool isOwner = celli_ == ownerCellI; const bool isOwner = celli_ == ownerCellI;
celli_ = isOwner ? mesh_.faceNeighbour()[tetFacei_] : ownerCellI; celli_ = isOwner ? mesh_.faceNeighbour()[tetFacei_] : ownerCellI;
// Reflect to account for the change of triangle orientation in the new cell // Reflect to account for the change of triangle orientation in the new cell
reflect(); reflect();
} }
@ -414,78 +413,84 @@ void Foam::particle::locate
const string& boundaryMsg const string& boundaryMsg
) )
{ {
if (debug)
{
Info << "Particle " << origId() << nl << FUNCTION_NAME << nl << endl;
}
celli_ = celli; celli_ = celli;
// Find the cell, if it has not been given // Find the cell, if it has not been given
if (celli_ < 0) if (celli < 0)
{ {
celli_ = mesh_.cellTree().findInside(position); celli_ = mesh_.cellTree().findInside(position);
} }
if (celli_ < 0) if (celli < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Cell not found for particle position " << position << "." << "Cell not found for particle position " << position << "."
<< exit(FatalError); << exit(FatalError);
} }
// Put the particle at (almost) the cell centre and in a random tet. const vector displacement = position - mesh_.cellCentres()[celli_];
// Note perturbing the cell centre to make sure we find at least one
// tet containing it. With start point exactly at the cell centre very // Loop all cell tets to find the one containing the position. Track
// occasionally it would not get found in any of the tets // through each tet from the cell centre. If a tet contains the position
coordinates_ = barycentric(1-3*SMALL, SMALL, SMALL, SMALL); // then the track will end with a single trackToTri.
tetFacei_ = mesh_.cells()[celli_][0]; const class cell& c = mesh_.cells()[celli_];
tetPti_ = 1; scalar minF = VGREAT;
label minTetFacei = -1, minTetPti = -1;
forAll(c, cellTetFacei)
{
const class face& f = mesh_.faces()[c[cellTetFacei]];
for (label tetPti = 1; tetPti < f.size() - 1; ++tetPti)
{
coordinates_ = barycentric(1, 0, 0, 0);
tetFacei_ = c[cellTetFacei];
tetPti_ = tetPti;
facei_ = -1; facei_ = -1;
// Track to the injection point label tetTriI = -1;
track(position - this->position(), 0); const scalar f = trackToTri(displacement, 0, tetTriI);
if (tetTriI == -1)
{
return;
}
if (f < minF)
{
minF = f;
minTetFacei = tetFacei_;
minTetPti = tetPti_;
}
}
}
// The particle must be (hopefully only slightly) outside the cell. Track
// into the tet which got the furthest.
coordinates_ = barycentric(1, 0, 0, 0);
tetFacei_ = minTetFacei;
tetPti_ = minTetPti;
facei_ = -1;
track(displacement, 0);
if (!onFace()) if (!onFace())
{ {
return; return;
} }
// We hit a boundary ... // If we are here then we hit a boundary
if (boundaryFail) if (boundaryFail)
{ {
FatalErrorInFunction << boundaryMsg FatalErrorInFunction << boundaryMsg << exit(FatalError);
<< " when tracking from centre " << mesh_.cellCentres()[celli_]
<< " of cell " << celli_ << " to position " << position
<< exit(FatalError);
} }
else else
{ {
// Re-do the track, but this time do the bit tangential to the
// direction/patch first. This gets us as close as possible to the
// original path/position.
if (direction == nullptr)
{
const polyPatch& p = mesh_.boundaryMesh()[patch()];
direction = &p.faceNormals()[p.whichFace(facei_)];
}
const vector n = *direction/mag(*direction);
const vector s = position - mesh_.cellCentres()[celli_];
const vector sN = (s & n)*n;
const vector sT = s - sN;
coordinates_ = barycentric(1, 0, 0, 0);
tetFacei_ = mesh_.cells()[celli_][0];
tetPti_ = 1;
facei_ = -1;
track(sT, 0);
track(sN, 0);
static label nWarnings = 0; static label nWarnings = 0;
static const label maxNWarnings = 100; static const label maxNWarnings = 100;
if (nWarnings < maxNWarnings) if ((nWarnings < maxNWarnings) && boundaryFail)
{ {
WarningInFunction << boundaryMsg.c_str() WarningInFunction << boundaryMsg.c_str() << endl;
<< " when tracking from centre " << mesh_.cellCentres()[celli_]
<< " of cell " << celli_ << " to position " << position
<< endl;
++ nWarnings; ++ nWarnings;
} }
if (nWarnings == maxNWarnings) if (nWarnings == maxNWarnings)
@ -496,6 +501,7 @@ void Foam::particle::locate
++ nWarnings; ++ nWarnings;
} }
} }
} }
@ -516,7 +522,9 @@ Foam::particle::particle
tetFacei_(tetFacei), tetFacei_(tetFacei),
tetPti_(tetPti), tetPti_(tetPti),
facei_(-1), facei_(-1),
stepFraction_(0.0), stepFraction_(1.0),
behind_(0.0),
nBehind_(0),
origProc_(Pstream::myProcNo()), origProc_(Pstream::myProcNo()),
origId_(getNewParticleID()) origId_(getNewParticleID())
{} {}
@ -535,7 +543,9 @@ Foam::particle::particle
tetFacei_(-1), tetFacei_(-1),
tetPti_(-1), tetPti_(-1),
facei_(-1), facei_(-1),
stepFraction_(0.0), stepFraction_(1.0),
behind_(0.0),
nBehind_(0),
origProc_(Pstream::myProcNo()), origProc_(Pstream::myProcNo()),
origId_(getNewParticleID()) origId_(getNewParticleID())
{ {
@ -566,7 +576,9 @@ Foam::particle::particle
tetFacei_(tetFacei), tetFacei_(tetFacei),
tetPti_(tetPti), tetPti_(tetPti),
facei_(-1), facei_(-1),
stepFraction_(0.0), stepFraction_(1.0),
behind_(0.0),
nBehind_(0),
origProc_(Pstream::myProcNo()), origProc_(Pstream::myProcNo()),
origId_(getNewParticleID()) origId_(getNewParticleID())
{ {
@ -593,6 +605,8 @@ Foam::particle::particle(const particle& p)
tetPti_(p.tetPti_), tetPti_(p.tetPti_),
facei_(p.facei_), facei_(p.facei_),
stepFraction_(p.stepFraction_), stepFraction_(p.stepFraction_),
behind_(p.behind_),
nBehind_(p.nBehind_),
origProc_(p.origProc_), origProc_(p.origProc_),
origId_(p.origId_) origId_(p.origId_)
{} {}
@ -607,6 +621,8 @@ Foam::particle::particle(const particle& p, const polyMesh& mesh)
tetPti_(p.tetPti_), tetPti_(p.tetPti_),
facei_(p.facei_), facei_(p.facei_),
stepFraction_(p.stepFraction_), stepFraction_(p.stepFraction_),
behind_(p.behind_),
nBehind_(p.nBehind_),
origProc_(p.origProc_), origProc_(p.origProc_),
origId_(p.origId_) origId_(p.origId_)
{} {}
@ -645,7 +661,8 @@ Foam::scalar Foam::particle::trackToFace
facei_ = -1; facei_ = -1;
while (true) // Loop the tets in the current cell
while (nBehind_ < maxNBehind_)
{ {
f *= trackToTri(f*displacement, f*fraction, tetTriI); f *= trackToTri(f*displacement, f*fraction, tetTriI);
@ -666,6 +683,25 @@ Foam::scalar Foam::particle::trackToFace
changeTet(tetTriI); changeTet(tetTriI);
} }
} }
// Warn if stuck, and incorrectly advance the step fraction to completion
static label stuckID = -1, stuckProc = -1;
if (origId_ != stuckID && origProc_ != stuckProc)
{
WarningInFunction
<< "Particle #" << origId_ << " got stuck at " << position()
<< endl;
}
stuckID = origId_;
stuckProc = origProc_;
stepFraction_ += f*fraction;
behind_ = 0;
nBehind_ = 0;
return 0;
} }
@ -702,11 +738,8 @@ Foam::scalar Foam::particle::trackToStationaryTri
<< "Start local coordinates = " << y0 << endl; << "Start local coordinates = " << y0 << endl;
} }
// Get the factor by which the displacement is increased
const scalar f = detA >= 0 ? 1 : negativeSpaceDisplacementFactor;
// Calculate the local tracking displacement // Calculate the local tracking displacement
barycentric Tx1(f*x1 & T); barycentric Tx1(x1 & T);
if (debug) if (debug)
{ {
@ -718,7 +751,7 @@ Foam::scalar Foam::particle::trackToStationaryTri
scalar muH = std::isnormal(detA) && detA <= 0 ? VGREAT : 1/detA; scalar muH = std::isnormal(detA) && detA <= 0 ? VGREAT : 1/detA;
for (label i = 0; i < 4; ++ i) for (label i = 0; i < 4; ++ i)
{ {
if (std::isnormal(Tx1[i]) && Tx1[i] < 0) if (Tx1[i] < - detA*SMALL)
{ {
scalar mu = - y0[i]/Tx1[i]; scalar mu = - y0[i]/Tx1[i];
@ -776,6 +809,30 @@ Foam::scalar Foam::particle::trackToStationaryTri
// Set the proportion of the track that has been completed // Set the proportion of the track that has been completed
stepFraction_ += fraction*muH*detA; stepFraction_ += fraction*muH*detA;
if (debug)
{
Info << "Step Fraction : " << stepFraction_ << endl;
Info << "fraction*muH*detA : " << fraction*muH*detA << endl;
Info << "static muH : " << muH << endl;
Info << "origId() : " << origId() << endl;
}
// Accumulate displacement behind
if (detA <= 0 || nBehind_ > 0)
{
behind_ += muH*detA*mag(displacement);
if (behind_ > 0)
{
behind_ = 0;
nBehind_ = 0;
}
else
{
++ nBehind_;
}
}
return iH != -1 ? 1 - muH*detA : 0; return iH != -1 ? 1 - muH*detA : 0;
} }
@ -803,12 +860,20 @@ Foam::scalar Foam::particle::trackToMovingTri
FixedList<barycentricTensor, 3> T; FixedList<barycentricTensor, 3> T;
movingTetReverseTransform(fraction, centre, detA, T); movingTetReverseTransform(fraction, centre, detA, T);
// Get the factor by which the displacement is increased if (debug)
const scalar f = detA[0] >= 0 ? 1 : negativeSpaceDisplacementFactor; {
Pair<vector> o, b, v1, v2;
movingTetGeometry(fraction, o, b, v1, v2);
Info<< "Tet points o=" << o[0] << ", b=" << b[0]
<< ", v1=" << v1[0] << ", v2=" << v2[0] << endl
<< "Tet determinant = " << detA[0] << endl
<< "Start local coordinates = " << y0[0] << endl;
}
// Get the relative global position // Get the relative global position
const vector x0Rel = x0 - centre[0]; const vector x0Rel = x0 - centre[0];
const vector x1Rel = f*x1 - centre[1]; const vector x1Rel = x1 - centre[1];
// Form the determinant and hit equations // Form the determinant and hit equations
cubicEqn detAEqn(sqr(detA[0])*detA[3], detA[0]*detA[2], detA[1], 1); cubicEqn detAEqn(sqr(detA[0])*detA[3], detA[0]*detA[2], detA[1], 1);
@ -826,6 +891,16 @@ Foam::scalar Foam::particle::trackToMovingTri
hitEqn[i] = cubicEqn(hitEqnA[i], hitEqnB[i], hitEqnC[i], hitEqnD[i]); hitEqn[i] = cubicEqn(hitEqnA[i], hitEqnB[i], hitEqnC[i], hitEqnD[i]);
} }
if (debug)
{
for (label i = 0; i < 4; ++ i)
{
Info<< (i ? " " : "Hit equation ") << i << " = "
<< hitEqn[i] << endl;
}
Info<< " DetA equation = " << detA << endl;
}
// Calculate the hit fraction // Calculate the hit fraction
label iH = -1; label iH = -1;
scalar muH = std::isnormal(detA[0]) && detA[0] <= 0 ? VGREAT : 1/detA[0]; scalar muH = std::isnormal(detA[0]) && detA[0] <= 0 ? VGREAT : 1/detA[0];
@ -835,8 +910,33 @@ Foam::scalar Foam::particle::trackToMovingTri
for (label j = 0; j < 3; ++j) for (label j = 0; j < 3; ++j)
{ {
if (mu.type(j) == roots::real && hitEqn[i].derivative(mu[j]) < 0) if
(
mu.type(j) == roots::real
&& hitEqn[i].derivative(mu[j]) < - detA[0]*SMALL
)
{ {
if (debug)
{
const barycentric yH
(
hitEqn[0].value(mu[j]),
hitEqn[1].value(mu[j]),
hitEqn[2].value(mu[j]),
hitEqn[3].value(mu[j])
);
const scalar detAH = detAEqn.value(mu[j]);
Info<< "Hit on tet face " << i << " at local coordinate "
<< (std::isnormal(detAH) ? name(yH/detAH) : "???")
<< ", " << mu[j]*detA[0]*100 << "% of the "
<< "way along the track" << endl;
Info<< "derivative : " << hitEqn[i].derivative(mu[j]) << nl
<< " coord " << j << " mu[j]: " << mu[j] << nl
<< " hitEq " << i << endl;
}
if (0 <= mu[j] && mu[j] < muH) if (0 <= mu[j] && mu[j] < muH)
{ {
iH = i; iH = i;
@ -887,8 +987,26 @@ Foam::scalar Foam::particle::trackToMovingTri
coordinates_ = yH; coordinates_ = yH;
tetTriI = iH; tetTriI = iH;
scalar advance = muH*detA[0];
// Set the proportion of the track that has been completed // Set the proportion of the track that has been completed
stepFraction_ += fraction*muH*detA[0]; stepFraction_ += fraction*advance;
// Accumulate displacement behind
if (detA[0] <= 0 || nBehind_ > 0)
{
behind_ += muH*detA[0]*mag(displacement);
if (behind_ > 0)
{
behind_ = 0;
nBehind_ = 0;
}
else
{
++ nBehind_;
}
}
if (debug) if (debug)
{ {
@ -900,10 +1018,15 @@ Foam::scalar Foam::particle::trackToMovingTri
{ {
Pout<< "Track hit no tet faces" << endl; Pout<< "Track hit no tet faces" << endl;
} }
Pout<< "End local coordinates = " << yH << endl // Pout<< "End local coordinates = " << yH << endl
<< "End global coordinates = " << position() << endl; // << "End global coordinates = " << position() << endl
// << "Tracking displacement = " << position() - x0 << endl
// << muH*detA[0]*100 << "% of the step from " << stepFraction_
// << " to " << stepFraction_ + fraction << " completed" << endl
// << endl;
} }
return iH != -1 ? 1 - muH*detA[0] : 0; return iH != -1 ? 1 - muH*detA[0] : 0;
} }
@ -915,7 +1038,7 @@ Foam::scalar Foam::particle::trackToTri
label& tetTriI label& tetTriI
) )
{ {
if (mesh_.moving()) if ((mesh_.moving() && (stepFraction_ != 1 || fraction != 0)))
{ {
return trackToMovingTri(displacement, fraction, tetTriI); return trackToMovingTri(displacement, fraction, tetTriI);
} }
@ -1049,7 +1172,7 @@ void Foam::particle::correctAfterInteractionListReferral(const label celli)
// so this approximate topology is good enough. By using the nearby cell we // so this approximate topology is good enough. By using the nearby cell we
// minimise the error associated with the incorrect topology. // minimise the error associated with the incorrect topology.
coordinates_ = barycentric(1, 0, 0, 0); coordinates_ = barycentric(1, 0, 0, 0);
if (mesh_.moving()) if (mesh_.moving() && stepFraction_ != 1)
{ {
Pair<vector> centre; Pair<vector> centre;
FixedList<scalar, 4> detA; FixedList<scalar, 4> detA;

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2019 OpenCFD Ltd. Copyright (C) 2017-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -78,7 +78,7 @@ class particle
: :
public IDLList<particle>::link public IDLList<particle>::link
{ {
// Private member data // Private Data
//- Size in bytes of the position data //- Size in bytes of the position data
static const std::size_t sizeofPosition; static const std::size_t sizeofPosition;
@ -86,15 +86,9 @@ class particle
//- Size in bytes of the fields //- Size in bytes of the fields
static const std::size_t sizeofFields; static const std::size_t sizeofFields;
//- The factor by which the displacement is increased when passing //- The value of nBehind_ at which tracking is abandoned. See the
// through negative space. This should be slightly bigger than one. // description of nBehind_.
// This is needed as a straight trajectory can form a closed loop static const label maxNBehind_;
// through regions of overlapping positive and negative space, leading
// to a track which never ends. By increasing the rate of displacement
// through negative regions, the change in track fraction over this
// part of the loop no longer exactly cancels the change over the
// positive part, and the track therefore terminates.
static const scalar negativeSpaceDisplacementFactor;
public: public:
@ -103,7 +97,7 @@ public:
{ {
public: public:
// Public data // Public Data
//- Flag to switch processor //- Flag to switch processor
bool switchProcessor; bool switchProcessor;
@ -135,7 +129,7 @@ public:
private: private:
// Private data // Private Data
//- Reference to the polyMesh database //- Reference to the polyMesh database
const polyMesh& mesh_; const polyMesh& mesh_;
@ -147,12 +141,12 @@ private:
label celli_; label celli_;
//- Index of the face that owns the decomposed tet that the //- Index of the face that owns the decomposed tet that the
// particle is in //- particle is in
label tetFacei_; label tetFacei_;
//- Index of the point on the face that defines the decomposed //- Index of the point on the face that defines the decomposed
// tet that the particle is in. Relative to the face base //- tet that the particle is in. Relative to the face base
// point. //- point.
label tetPti_; label tetPti_;
//- Face index if the particle is on a face otherwise -1 //- Face index if the particle is on a face otherwise -1
@ -161,6 +155,18 @@ private:
//- Fraction of time-step completed //- Fraction of time-step completed
scalar stepFraction_; scalar stepFraction_;
//- The distance behind the maximum distance reached so far
scalar behind_;
//- The number of tracks carried out that ended in a distance behind the
//- maximum distance reached so far. Once this reaches maxNBehind_,
// tracking is abandoned for the current step. This is needed because
// when tetrahedra are inverted a straight trajectory can form a closed
// loop through regions of overlapping positive and negative space.
// Without this break clause, such loops can result in a valid track
// which never ends.
label nBehind_;
//- Originating processor id //- Originating processor id
label origProc_; label origProc_;
@ -331,7 +337,7 @@ protected:
public: public:
// Static data members // Static Data Members
//- Runtime type information //- Runtime type information
TypeName("particle"); TypeName("particle");
@ -526,6 +532,9 @@ public:
//- Return current particle position //- Return current particle position
inline vector position() const; inline vector position() const;
//- Reset particle data
inline void reset();
// Track // Track
@ -664,6 +673,7 @@ public:
void relocate(const point& position, const label celli = -1); void relocate(const point& position, const label celli = -1);
// I-O // I-O
//- Write the name representation to stream //- Write the name representation to stream

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2018 OpenFOAM Foundation Copyright (C) 2011-2018 OpenFOAM Foundation
Copyright (C) 2011-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -68,6 +69,7 @@ inline void Foam::particle::movingTetGeometry
) const ) const
{ {
const triFace triIs(currentTetIndices().faceTriIs(mesh_)); const triFace triIs(currentTetIndices().faceTriIs(mesh_));
const pointField& ptsOld = mesh_.oldPoints(); const pointField& ptsOld = mesh_.oldPoints();
const pointField& ptsNew = mesh_.points(); const pointField& ptsNew = mesh_.points();
@ -75,8 +77,11 @@ inline void Foam::particle::movingTetGeometry
// we need to put a mesh_.oldCellCentres() method in for this to work. The // we need to put a mesh_.oldCellCentres() method in for this to work. The
// values obtained from the mesh and those obtained from the cell do not // values obtained from the mesh and those obtained from the cell do not
// necessarily match. See mantis #1993. // necessarily match. See mantis #1993.
const vector ccOld = mesh_.cells()[celli_].centre(ptsOld, mesh_.faces()); //const vector ccOld = mesh_.cells()[celli_].centre(ptsOld, mesh_.faces());
const vector ccNew = mesh_.cells()[celli_].centre(ptsNew, mesh_.faces()); //const vector ccNew = mesh_.cells()[celli_].centre(ptsNew, mesh_.faces());
const vector ccOld = mesh_.oldCellCentres()[celli_];
const vector ccNew = mesh_.cellCentres()[celli_];
// Old and new points and cell centres are not sub-cycled. If we are sub- // Old and new points and cell centres are not sub-cycled. If we are sub-
// cycling, then we have to account for the timestep change here by // cycling, then we have to account for the timestep change here by
@ -265,7 +270,7 @@ inline Foam::tetIndices Foam::particle::currentTetIndices() const
inline Foam::barycentricTensor Foam::particle::currentTetTransform() const inline Foam::barycentricTensor Foam::particle::currentTetTransform() const
{ {
if (mesh_.moving()) if (mesh_.moving() && stepFraction_ != 1)
{ {
return movingTetTransform(0)[0]; return movingTetTransform(0)[0];
} }
@ -312,6 +317,14 @@ inline Foam::vector Foam::particle::position() const
} }
inline void Foam::particle::reset()
{
stepFraction_ = 0;
nBehind_ = 0;
behind_ = 0;
}
void Foam::particle::patchData(vector& n, vector& U) const void Foam::particle::patchData(vector& n, vector& U) const
{ {
if (!onBoundaryFace()) if (!onBoundaryFace())
@ -321,7 +334,7 @@ void Foam::particle::patchData(vector& n, vector& U) const
<< exit(FatalError); << exit(FatalError);
} }
if (mesh_.moving()) if ((mesh_.moving() && stepFraction_ != 1))
{ {
Pair<vector> centre, base, vertex1, vertex2; Pair<vector> centre, base, vertex1, vertex2;
movingTetGeometry(1, centre, base, vertex1, vertex2); movingTetGeometry(1, centre, base, vertex1, vertex2);

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd. Copyright (C) 2016-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -293,7 +293,7 @@ void Foam::particle::writeObjects(const CloudType& c, objectRegistry& obr)
template<class TrackCloudType> template<class TrackCloudType>
void Foam::particle::hitFace void Foam::particle::hitFace
( (
const vector& direction, const vector& displacement,
TrackCloudType& cloud, TrackCloudType& cloud,
trackingData& td trackingData& td
) )
@ -337,11 +337,11 @@ void Foam::particle::hitFace
} }
else if (isA<cyclicACMIPolyPatch>(patch)) else if (isA<cyclicACMIPolyPatch>(patch))
{ {
p.hitCyclicACMIPatch(cloud, ttd, direction); p.hitCyclicACMIPatch(cloud, ttd, displacement);
} }
else if (isA<cyclicAMIPolyPatch>(patch)) else if (isA<cyclicAMIPolyPatch>(patch))
{ {
p.hitCyclicAMIPatch(cloud, ttd, direction); p.hitCyclicAMIPatch(cloud, ttd, displacement);
} }
else if (isA<processorPolyPatch>(patch)) else if (isA<processorPolyPatch>(patch))
{ {
@ -459,7 +459,7 @@ void Foam::particle::hitCyclicAMIPatch
( (
TrackCloudType&, TrackCloudType&,
trackingData& td, trackingData& td,
const vector& direction const vector& displacement
) )
{ {
vector pos = position(); vector pos = position();
@ -468,7 +468,14 @@ void Foam::particle::hitCyclicAMIPatch
static_cast<const cyclicAMIPolyPatch&>(mesh_.boundaryMesh()[patch()]); static_cast<const cyclicAMIPolyPatch&>(mesh_.boundaryMesh()[patch()]);
const cyclicAMIPolyPatch& receiveCpp = cpp.neighbPatch(); const cyclicAMIPolyPatch& receiveCpp = cpp.neighbPatch();
const label sendFacei = cpp.whichFace(facei_); const label sendFacei = cpp.whichFace(facei_);
const label receiveFacei = cpp.pointFace(sendFacei, direction, pos); const label receiveFacei = cpp.pointFace(sendFacei, displacement, pos);
if (false)
{
Info<< "My new pos : " << pos << endl;
Info<< "Particle " << origId() << " crossing AMI from " << cpp.name()
<< " to " << receiveCpp.name() << endl << endl;
}
if (receiveFacei < 0) if (receiveFacei < 0)
{ {
@ -485,12 +492,13 @@ void Foam::particle::hitCyclicAMIPatch
facei_ = tetFacei_ = receiveFacei + receiveCpp.start(); facei_ = tetFacei_ = receiveFacei + receiveCpp.start();
// Locate the particle on the receiving side // Locate the particle on the receiving side
vector directionT = direction; vector displacementT = displacement;
cpp.reverseTransformDirection(directionT, sendFacei); cpp.reverseTransformDirection(displacementT, sendFacei);
locate locate
( (
pos, pos,
&directionT, &displacementT,
mesh_.faceOwner()[facei_], mesh_.faceOwner()[facei_],
false, false,
"Particle crossed between " + cyclicAMIPolyPatch::typeName + "Particle crossed between " + cyclicAMIPolyPatch::typeName +
@ -523,6 +531,27 @@ void Foam::particle::hitCyclicAMIPatch
); );
transformProperties(-s); transformProperties(-s);
} }
//if (onBoundaryFace())
{
//DebugVar("On boudanry")
// vector receiveNormal, receiveDisplacement;
// patchData(receiveNormal, receiveDisplacement);
//
// if (((displacementT - fraction*receiveDisplacement)&receiveNormal) > 0)
// {
// td.keepParticle = false;
// WarningInFunction
// << "Particle transfer from " << cyclicAMIPolyPatch::typeName
// << " patches " << cpp.name() << " to " << receiveCpp.name()
// << " failed at position " << pos << " and with displacement "
// << (displacementT - fraction*receiveDisplacement) << nl
// << " The displacement points into both the source and "
// << "receiving faces, so the tracking cannot proceed" << nl
// << " The particle has been removed" << nl << endl;
// return;
// }
}
} }
@ -531,7 +560,7 @@ void Foam::particle::hitCyclicACMIPatch
( (
TrackCloudType& cloud, TrackCloudType& cloud,
trackingData& td, trackingData& td,
const vector& direction const vector& displacement
) )
{ {
const cyclicACMIPolyPatch& cpp = const cyclicACMIPolyPatch& cpp =
@ -551,20 +580,20 @@ void Foam::particle::hitCyclicACMIPatch
if (!couple && !nonOverlap) if (!couple && !nonOverlap)
{ {
vector pos = position(); vector pos = position();
couple = cpp.pointFace(localFacei, direction, pos) >= 0; couple = cpp.pointFace(localFacei, displacement, pos) >= 0;
nonOverlap = !couple; nonOverlap = !couple;
} }
if (couple) if (couple)
{ {
hitCyclicAMIPatch(cloud, td, direction); hitCyclicAMIPatch(cloud, td, displacement);
} }
else else
{ {
// Move to the face associated with the non-overlap patch and redo the // Move to the face associated with the non-overlap patch and redo the
// face interaction. // face interaction.
tetFacei_ = facei_ = cpp.nonOverlapPatch().start() + localFacei; tetFacei_ = facei_ = cpp.nonOverlapPatch().start() + localFacei;
hitFace(direction, cloud, td); hitFace(displacement, cloud, td);
} }
} }