mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: wallBoundedStreamline: survive neg-tet cells. Fixes #502.
This commit is contained in:
@ -3,7 +3,7 @@
|
|||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -35,6 +35,57 @@ const std::size_t Foam::wallBoundedParticle::sizeofFields_
|
|||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::tetIndices Foam::wallBoundedParticle::currentTetIndices() const
|
||||||
|
{
|
||||||
|
// Replacement for particle::currentTetIndices that avoids error
|
||||||
|
// upon invalid tetBasePtIs
|
||||||
|
|
||||||
|
const faceList& pFaces = mesh_.faces();
|
||||||
|
const labelList& pOwner = mesh_.faceOwner();
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[tetFacei_];
|
||||||
|
|
||||||
|
bool own = (pOwner[tetFacei_] == celli_);
|
||||||
|
|
||||||
|
label faceBasePtI = mesh_.tetBasePtIs()[tetFacei_];
|
||||||
|
if (faceBasePtI == -1)
|
||||||
|
{
|
||||||
|
//WarningInFunction
|
||||||
|
// << "No base point for face " << tetFacei_ << ", " << f
|
||||||
|
// << ", produces a decomposition that has a minimum "
|
||||||
|
// << "volume greater than tolerance."
|
||||||
|
// << endl;
|
||||||
|
faceBasePtI = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label facePtI = (tetPti_ + faceBasePtI) % f.size();
|
||||||
|
label otherFacePtI = f.fcIndex(facePtI);
|
||||||
|
|
||||||
|
label facePtAI;
|
||||||
|
label facePtBI;
|
||||||
|
if (own)
|
||||||
|
{
|
||||||
|
facePtAI = facePtI;
|
||||||
|
facePtBI = otherFacePtI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
facePtAI = otherFacePtI;
|
||||||
|
facePtBI = facePtI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tetIndices
|
||||||
|
(
|
||||||
|
celli_,
|
||||||
|
tetFacei_,
|
||||||
|
faceBasePtI,
|
||||||
|
facePtAI,
|
||||||
|
facePtBI,
|
||||||
|
tetPti_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::edge Foam::wallBoundedParticle::currentEdge() const
|
Foam::edge Foam::wallBoundedParticle::currentEdge() const
|
||||||
{
|
{
|
||||||
if ((meshEdgeStart_ != -1) == (diagEdge_ != -1))
|
if ((meshEdgeStart_ != -1) == (diagEdge_ != -1))
|
||||||
@ -57,6 +108,18 @@ Foam::edge Foam::wallBoundedParticle::currentEdge() const
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
label faceBasePti = mesh_.tetBasePtIs()[tetFace()];
|
label faceBasePti = mesh_.tetBasePtIs()[tetFace()];
|
||||||
|
if (faceBasePti == -1)
|
||||||
|
{
|
||||||
|
//FatalErrorInFunction
|
||||||
|
//WarningInFunction
|
||||||
|
// << "No base point for face " << tetFace() << ", " << f
|
||||||
|
// << ", produces a decomposition that has a minimum "
|
||||||
|
// << "volume greater than tolerance."
|
||||||
|
// //<< abort(FatalError);
|
||||||
|
// << endl;
|
||||||
|
faceBasePti = 0;
|
||||||
|
}
|
||||||
|
|
||||||
label diagPti = (faceBasePti+diagEdge_)%f.size();
|
label diagPti = (faceBasePti+diagEdge_)%f.size();
|
||||||
|
|
||||||
return edge(f[faceBasePti], f[diagPti]);
|
return edge(f[faceBasePti], f[diagPti]);
|
||||||
@ -66,11 +129,118 @@ Foam::edge Foam::wallBoundedParticle::currentEdge() const
|
|||||||
|
|
||||||
void Foam::wallBoundedParticle::crossEdgeConnectedFace
|
void Foam::wallBoundedParticle::crossEdgeConnectedFace
|
||||||
(
|
(
|
||||||
const edge& meshEdge
|
const label& celli,
|
||||||
|
label& tetFacei,
|
||||||
|
label& tetPti,
|
||||||
|
const edge& e
|
||||||
)
|
)
|
||||||
|
{
|
||||||
|
const faceList& pFaces = mesh_.faces();
|
||||||
|
const cellList& pCells = mesh_.cells();
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[tetFacei];
|
||||||
|
|
||||||
|
const Foam::cell& thisCell = pCells[celli];
|
||||||
|
|
||||||
|
forAll(thisCell, cFI)
|
||||||
|
{
|
||||||
|
// Loop over all other faces of this cell and
|
||||||
|
// find the one that shares this edge
|
||||||
|
|
||||||
|
label fI = thisCell[cFI];
|
||||||
|
|
||||||
|
if (tetFacei == fI)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Foam::face& otherFace = pFaces[fI];
|
||||||
|
|
||||||
|
label edDir = otherFace.edgeDirection(e);
|
||||||
|
|
||||||
|
if (edDir == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (f == pFaces[fI])
|
||||||
|
{
|
||||||
|
// This is a necessary condition if using duplicate baffles
|
||||||
|
// (so coincident faces). We need to make sure we don't cross into
|
||||||
|
// the face with the same vertices since we might enter a tracking
|
||||||
|
// loop where it never exits. This test should be cheap
|
||||||
|
// for most meshes so can be left in for 'normal' meshes.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Found edge on other face
|
||||||
|
tetFacei = fI;
|
||||||
|
|
||||||
|
label eIndex = -1;
|
||||||
|
|
||||||
|
if (edDir == 1)
|
||||||
|
{
|
||||||
|
// Edge is in the forward circulation of this face, so
|
||||||
|
// work with the start point of the edge
|
||||||
|
eIndex = findIndex(otherFace, e.start());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// edDir == -1, so the edge is in the reverse
|
||||||
|
// circulation of this face, so work with the end
|
||||||
|
// point of the edge
|
||||||
|
eIndex = findIndex(otherFace, e.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
label tetBasePtI = mesh_.tetBasePtIs()[fI];
|
||||||
|
|
||||||
|
if (tetBasePtI == -1)
|
||||||
|
{
|
||||||
|
//FatalErrorInFunction
|
||||||
|
//WarningInFunction
|
||||||
|
// << "No base point for face " << fI << ", " << f
|
||||||
|
// << ", produces a decomposition that has a minimum "
|
||||||
|
// << "volume greater than tolerance."
|
||||||
|
// //<< abort(FatalError);
|
||||||
|
// << endl;
|
||||||
|
tetBasePtI = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find eIndex relative to the base point on new face
|
||||||
|
eIndex -= tetBasePtI;
|
||||||
|
|
||||||
|
if (neg(eIndex))
|
||||||
|
{
|
||||||
|
eIndex = (eIndex + otherFace.size()) % otherFace.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eIndex == 0)
|
||||||
|
{
|
||||||
|
// The point is the base point, so this is first tet
|
||||||
|
// in the face circulation
|
||||||
|
tetPti = 1;
|
||||||
|
}
|
||||||
|
else if (eIndex == otherFace.size() - 1)
|
||||||
|
{
|
||||||
|
// The point is the last before the base point, so
|
||||||
|
// this is the last tet in the face circulation
|
||||||
|
tetPti = otherFace.size() - 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tetPti = eIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::wallBoundedParticle::crossEdgeConnectedFace(const edge& meshEdge)
|
||||||
{
|
{
|
||||||
// Update tetFace, tetPt
|
// Update tetFace, tetPt
|
||||||
particle::crossEdgeConnectedFace(cell(), tetFace(), tetPt(), meshEdge);
|
crossEdgeConnectedFace(cell(), tetFace(), tetPt(), meshEdge);
|
||||||
|
|
||||||
// Update face to be same as tracking one
|
// Update face to be same as tracking one
|
||||||
face() = tetFace();
|
face() = tetFace();
|
||||||
@ -164,14 +334,13 @@ void Foam::wallBoundedParticle::crossDiagonalEdge()
|
|||||||
|
|
||||||
Foam::scalar Foam::wallBoundedParticle::trackFaceTri
|
Foam::scalar Foam::wallBoundedParticle::trackFaceTri
|
||||||
(
|
(
|
||||||
|
const vector& n,
|
||||||
const vector& endPosition,
|
const vector& endPosition,
|
||||||
label& minEdgei
|
label& minEdgei
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Track p from position to endPosition
|
// Track p from position to endPosition
|
||||||
const triFace tri(currentTetIndices().faceTriIs(mesh_));
|
const triFace tri(currentTetIndices().faceTriIs(mesh_));
|
||||||
vector n = tri.normal(mesh_.points());
|
|
||||||
n /= mag(n)+VSMALL;
|
|
||||||
|
|
||||||
// Check which edge intersects the trajectory.
|
// Check which edge intersects the trajectory.
|
||||||
// Project trajectory onto triangle
|
// Project trajectory onto triangle
|
||||||
@ -245,6 +414,7 @@ Foam::scalar Foam::wallBoundedParticle::trackFaceTri
|
|||||||
|
|
||||||
bool Foam::wallBoundedParticle::isTriAlongTrack
|
bool Foam::wallBoundedParticle::isTriAlongTrack
|
||||||
(
|
(
|
||||||
|
const vector& n,
|
||||||
const point& endPosition
|
const point& endPosition
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
@ -267,10 +437,6 @@ bool Foam::wallBoundedParticle::isTriAlongTrack
|
|||||||
|
|
||||||
const vector dir = endPosition-position();
|
const vector dir = endPosition-position();
|
||||||
|
|
||||||
// Get normal of currentE
|
|
||||||
vector n = triVerts.normal(mesh_.points());
|
|
||||||
n /= mag(n);
|
|
||||||
|
|
||||||
forAll(triVerts, i)
|
forAll(triVerts, i)
|
||||||
{
|
{
|
||||||
label j = triVerts.fcIndex(i);
|
label j = triVerts.fcIndex(i);
|
||||||
@ -382,7 +548,7 @@ Foam::Ostream& Foam::operator<<
|
|||||||
{
|
{
|
||||||
const wallBoundedParticle& p = ip.t_;
|
const wallBoundedParticle& p = ip.t_;
|
||||||
|
|
||||||
tetPointRef tpr(p.currentTet());
|
tetPointRef tpr(p.currentTetIndices().tet(p.mesh()));
|
||||||
|
|
||||||
os << " " << static_cast<const particle&>(p) << nl
|
os << " " << static_cast<const particle&>(p) << nl
|
||||||
<< " tet:" << nl;
|
<< " tet:" << nl;
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -123,6 +123,20 @@ protected:
|
|||||||
//- Construct current edge
|
//- Construct current edge
|
||||||
edge currentEdge() const;
|
edge currentEdge() const;
|
||||||
|
|
||||||
|
//- Replacement for particle::currentTetIndices() that avoids bombing
|
||||||
|
// out on invalid tet decomposition (tetBasePtIs = -1)
|
||||||
|
tetIndices currentTetIndices() const;
|
||||||
|
|
||||||
|
//- Replacement for particle::crossEdgeConnectedFace that avoids bombing
|
||||||
|
// out on invalid tet decomposition (tetBasePtIs = -1)
|
||||||
|
void crossEdgeConnectedFace
|
||||||
|
(
|
||||||
|
const label& celli,
|
||||||
|
label& tetFacei,
|
||||||
|
label& tetPti,
|
||||||
|
const edge& e
|
||||||
|
);
|
||||||
|
|
||||||
//- Cross mesh edge into different face on same cell
|
//- Cross mesh edge into different face on same cell
|
||||||
void crossEdgeConnectedFace(const edge& meshEdge);
|
void crossEdgeConnectedFace(const edge& meshEdge);
|
||||||
|
|
||||||
@ -130,10 +144,10 @@ protected:
|
|||||||
void crossDiagonalEdge();
|
void crossDiagonalEdge();
|
||||||
|
|
||||||
//- Track through single triangle
|
//- Track through single triangle
|
||||||
scalar trackFaceTri(const vector& endPosition, label& minEdgei);
|
scalar trackFaceTri(const vector& n, const vector& endPosition, label&);
|
||||||
|
|
||||||
//- Is current triangle in the track direction
|
//- Is current triangle in the track direction
|
||||||
bool isTriAlongTrack(const point& endPosition) const;
|
bool isTriAlongTrack(const vector& n, const point& endPosition) const;
|
||||||
|
|
||||||
|
|
||||||
// Patch interactions
|
// Patch interactions
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -175,7 +175,14 @@ Foam::scalar Foam::wallBoundedParticle::trackToEdge
|
|||||||
// endposition? i.e. since volume of nbr tet is positive the
|
// endposition? i.e. since volume of nbr tet is positive the
|
||||||
// tracking direction should be into the tet.
|
// tracking direction should be into the tet.
|
||||||
tetIndices nbrTi(nbrCelli, tetFacei_, tetPti_, mesh_);
|
tetIndices nbrTi(nbrCelli, tetFacei_, tetPti_, mesh_);
|
||||||
if ((nbrTi.faceTri(mesh_).normal() & (endPosition-position())) < 0)
|
|
||||||
|
bool posVol = (nbrTi.tet(mesh_).mag() > 0);
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
posVol
|
||||||
|
== ((nbrTi.faceTri(mesh_).normal() & (endPosition-position())) < 0)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Change into nbrCell. No need to change tetFace, tetPt.
|
// Change into nbrCell. No need to change tetFace, tetPt.
|
||||||
//Pout<< " crossed from cell:" << celli_
|
//Pout<< " crossed from cell:" << celli_
|
||||||
@ -213,12 +220,22 @@ Foam::scalar Foam::wallBoundedParticle::trackToEdge
|
|||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
point projectedEndPosition = endPosition;
|
|
||||||
// Remove normal component
|
|
||||||
{
|
|
||||||
const triFace tri(currentTetIndices().faceTriIs(mesh_));
|
const triFace tri(currentTetIndices().faceTriIs(mesh_));
|
||||||
vector n = tri.normal(mesh_.points());
|
vector n = tri.normal(mesh_.points());
|
||||||
n /= mag(n);
|
n /= mag(n);
|
||||||
|
|
||||||
|
point projectedEndPosition = endPosition;
|
||||||
|
|
||||||
|
const bool posVol = (currentTetIndices().tet(mesh_).mag() > 0);
|
||||||
|
|
||||||
|
if (!posVol)
|
||||||
|
{
|
||||||
|
// Negative tet volume. Track back by setting the end point
|
||||||
|
projectedEndPosition = position() - (endPosition-position());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove normal component
|
||||||
|
{
|
||||||
const point& basePt = mesh_.points()[tri[0]];
|
const point& basePt = mesh_.points()[tri[0]];
|
||||||
projectedEndPosition -= ((projectedEndPosition-basePt)&n)*n;
|
projectedEndPosition -= ((projectedEndPosition-basePt)&n)*n;
|
||||||
}
|
}
|
||||||
@ -234,7 +251,7 @@ Foam::scalar Foam::wallBoundedParticle::trackToEdge
|
|||||||
{
|
{
|
||||||
// See if the current triangle has got a point on the
|
// See if the current triangle has got a point on the
|
||||||
// correct side of the edge.
|
// correct side of the edge.
|
||||||
doTrack = isTriAlongTrack(projectedEndPosition);
|
doTrack = isTriAlongTrack(n, projectedEndPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -242,7 +259,7 @@ Foam::scalar Foam::wallBoundedParticle::trackToEdge
|
|||||||
{
|
{
|
||||||
// Track across triangle. Return triangle edge crossed.
|
// Track across triangle. Return triangle edge crossed.
|
||||||
label triEdgei = -1;
|
label triEdgei = -1;
|
||||||
trackFraction = trackFaceTri(projectedEndPosition, triEdgei);
|
trackFraction = trackFaceTri(n, projectedEndPosition, triEdgei);
|
||||||
|
|
||||||
if (triEdgei == -1)
|
if (triEdgei == -1)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -120,11 +120,12 @@ Foam::vector Foam::wallBoundedStreamLineParticle::sample
|
|||||||
{
|
{
|
||||||
// Stagnant particle. Might as well stop
|
// Stagnant particle. Might as well stop
|
||||||
lifeTime_ = 0;
|
lifeTime_ = 0;
|
||||||
|
return vector::zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return U/magU;
|
||||||
}
|
}
|
||||||
|
|
||||||
U /= magU;
|
|
||||||
|
|
||||||
return U;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -267,16 +268,6 @@ bool Foam::wallBoundedStreamLineParticle::move
|
|||||||
// Force removal
|
// Force removal
|
||||||
lifeTime_ = 0;
|
lifeTime_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if
|
|
||||||
(
|
|
||||||
!td.keepParticle
|
|
||||||
|| td.switchProcessor
|
|
||||||
|| lifeTime_ == 0
|
|
||||||
)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user