mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: tetOverlapVolume - improved robustness. Fixes #207
This commit is contained in:
@ -39,12 +39,6 @@ namespace Foam
|
|||||||
defineTypeNameAndDebug(tetOverlapVolume, 0);
|
defineTypeNameAndDebug(tetOverlapVolume, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When to consider a tet to be zero volume. We want to avoid doing clipping
|
|
||||||
// against negative volume tets. Tet volume can be calculated incorrectly
|
|
||||||
// due to truncation errors. The value below works for single and double
|
|
||||||
// precision but could probably be tighter for double precision.
|
|
||||||
Foam::scalar Foam::tetOverlapVolume::minTetVolume_ = SMALL*SMALL;
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|||||||
@ -54,12 +54,6 @@ class polyMesh;
|
|||||||
|
|
||||||
class tetOverlapVolume
|
class tetOverlapVolume
|
||||||
{
|
{
|
||||||
// Private data
|
|
||||||
|
|
||||||
//- Minimum tet volume to skip test
|
|
||||||
static scalar minTetVolume_;
|
|
||||||
|
|
||||||
|
|
||||||
// Private classes
|
// Private classes
|
||||||
|
|
||||||
//- tetPoints handling : sum resulting volumes
|
//- tetPoints handling : sum resulting volumes
|
||||||
|
|||||||
@ -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) 2015 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -45,51 +45,90 @@ void Foam::tetOverlapVolume::tetTetOverlap
|
|||||||
tetPointRef::storeOp cutInside(cutInsideTets, nCutInside);
|
tetPointRef::storeOp cutInside(cutInsideTets, nCutInside);
|
||||||
tetPointRef::dummyOp outside;
|
tetPointRef::dummyOp outside;
|
||||||
|
|
||||||
if (tetA.tet().mag() < minTetVolume_ || tetB.tet().mag() < minTetVolume_)
|
// Precompute the tet face areas and exit early if any face area is
|
||||||
|
// too small
|
||||||
|
static FixedList<vector, 4> tetAFaceAreas;
|
||||||
|
static FixedList<scalar, 4> tetAMag2FaceAreas;
|
||||||
|
tetPointRef tetATet = tetA.tet();
|
||||||
|
for (label facei = 0; facei < 4; ++facei)
|
||||||
{
|
{
|
||||||
return;
|
tetAFaceAreas[facei] = -tetATet.tri(facei).normal();
|
||||||
|
tetAMag2FaceAreas[facei] = magSqr(tetAFaceAreas[facei]);
|
||||||
|
if (tetAMag2FaceAreas[facei] < ROOTVSMALL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// face0
|
static FixedList<vector, 4> tetBFaceAreas;
|
||||||
plane pl0(tetB[1], tetB[3], tetB[2]);
|
static FixedList<scalar, 4> tetBMag2FaceAreas;
|
||||||
tetA.tet().sliceWithPlane(pl0, cutInside, outside);
|
tetPointRef tetBTet = tetB.tet();
|
||||||
if (nCutInside == 0)
|
for (label facei = 0; facei < 4; ++facei)
|
||||||
{
|
{
|
||||||
return;
|
tetBFaceAreas[facei] = -tetBTet.tri(facei).normal();
|
||||||
|
tetBMag2FaceAreas[facei] = magSqr(tetBFaceAreas[facei]);
|
||||||
|
if (tetBMag2FaceAreas[facei] < ROOTVSMALL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// face1
|
|
||||||
plane pl1(tetB[0], tetB[2], tetB[3]);
|
// Face 0
|
||||||
nInside = 0;
|
|
||||||
for (label i = 0; i < nCutInside; i++)
|
|
||||||
{
|
{
|
||||||
const tetPointRef t = cutInsideTets[i].tet();
|
vector n = tetBFaceAreas[0]/Foam::sqrt(tetBMag2FaceAreas[0]);
|
||||||
t.sliceWithPlane(pl1, inside, outside);
|
plane pl0(tetBTet.tri(0).a(), n, false);
|
||||||
}
|
|
||||||
if (nInside == 0)
|
tetA.tet().sliceWithPlane(pl0, cutInside, outside);
|
||||||
{
|
if (nCutInside == 0)
|
||||||
return;
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// face2
|
// Face 1
|
||||||
plane pl2(tetB[0], tetB[3], tetB[1]);
|
|
||||||
nCutInside = 0;
|
|
||||||
for (label i = 0; i < nInside; i++)
|
|
||||||
{
|
{
|
||||||
const tetPointRef t = insideTets[i].tet();
|
vector n = tetBFaceAreas[1]/Foam::sqrt(tetBMag2FaceAreas[1]);
|
||||||
t.sliceWithPlane(pl2, cutInside, outside);
|
plane pl1(tetBTet.tri(1).a(), n, false);
|
||||||
}
|
|
||||||
if (nCutInside == 0)
|
nInside = 0;
|
||||||
{
|
for (label i = 0; i < nCutInside; i++)
|
||||||
return;
|
{
|
||||||
|
const tetPointRef t = cutInsideTets[i].tet();
|
||||||
|
t.sliceWithPlane(pl1, inside, outside);
|
||||||
|
}
|
||||||
|
if (nInside == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// face3
|
// Face 2
|
||||||
plane pl3(tetB[0], tetB[1], tetB[2]);
|
|
||||||
for (label i = 0; i < nCutInside; i++)
|
|
||||||
{
|
{
|
||||||
const tetPointRef t = cutInsideTets[i].tet();
|
vector n = tetBFaceAreas[2]/Foam::sqrt(tetBMag2FaceAreas[2]);
|
||||||
t.sliceWithPlane(pl3, insideOp, outside);
|
plane pl2(tetBTet.tri(2).a(), n, false);
|
||||||
|
|
||||||
|
nCutInside = 0;
|
||||||
|
for (label i = 0; i < nInside; i++)
|
||||||
|
{
|
||||||
|
const tetPointRef t = insideTets[i].tet();
|
||||||
|
t.sliceWithPlane(pl2, cutInside, outside);
|
||||||
|
}
|
||||||
|
if (nCutInside == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Face 3
|
||||||
|
{
|
||||||
|
vector n = tetBFaceAreas[3]/Foam::sqrt(tetBMag2FaceAreas[3]);
|
||||||
|
plane pl3(tetBTet.tri(3).a(), n, false);
|
||||||
|
for (label i = 0; i < nCutInside; i++)
|
||||||
|
{
|
||||||
|
const tetPointRef t = cutInsideTets[i].tet();
|
||||||
|
t.sliceWithPlane(pl3, insideOp, outside);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user