Post-merge reorganisation
This commit is contained in:
parent
1db9942846
commit
30b9e79592
1 changed files with 597 additions and 0 deletions
597
src/dynamicMesh/dynamicFvMesh/dynamicTopoFvMesh/meshOpsI.H
Normal file
597
src/dynamicMesh/dynamicFvMesh/dynamicTopoFvMesh/meshOpsI.H
Normal file
|
@ -0,0 +1,597 @@
|
|||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright held by original author
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
meshOps
|
||||
|
||||
Description
|
||||
Various utility functions that perform mesh-related operations.
|
||||
|
||||
Author
|
||||
Sandeep Menon
|
||||
University of Massachusetts Amherst
|
||||
All rights reserved
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "Pair.H"
|
||||
#include "meshOps.H"
|
||||
#include "ListOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace meshOps
|
||||
{
|
||||
|
||||
// Utility method to find the common edge between two faces.
|
||||
inline bool findCommonEdge
|
||||
(
|
||||
const label first,
|
||||
const label second,
|
||||
const UList<labelList>& faceEdges,
|
||||
label& common
|
||||
)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
const labelList& fEi = faceEdges[first];
|
||||
const labelList& fEj = faceEdges[second];
|
||||
|
||||
forAll(fEi, edgeI)
|
||||
{
|
||||
forAll(fEj, edgeJ)
|
||||
{
|
||||
if (fEi[edgeI] == fEj[edgeJ])
|
||||
{
|
||||
common = fEi[edgeI];
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
// Utility method to find the interior (quad) / boundary (tri) faces
|
||||
// for an input quad-face and adjacent triangle-prism cell.
|
||||
inline void findPrismFaces
|
||||
(
|
||||
const label fIndex,
|
||||
const label cIndex,
|
||||
const UList<face>& faces,
|
||||
const UList<cell>& cells,
|
||||
const UList<label>& neighbour,
|
||||
FixedList<face,2>& bdyf,
|
||||
FixedList<label,2>& bidx,
|
||||
FixedList<face,2>& intf,
|
||||
FixedList<label,2>& iidx
|
||||
)
|
||||
{
|
||||
label indexO = 0, indexI = 0;
|
||||
|
||||
const cell& c = cells[cIndex];
|
||||
|
||||
forAll(c, i)
|
||||
{
|
||||
label faceIndex = c[i];
|
||||
|
||||
// Don't count the face under consideration
|
||||
if (faceIndex != fIndex)
|
||||
{
|
||||
const face& fi = faces[faceIndex];
|
||||
|
||||
if (neighbour[faceIndex] == -1)
|
||||
{
|
||||
if (fi.size() == 3)
|
||||
{
|
||||
// Triangular face on the boundary
|
||||
bidx[indexO] = faceIndex;
|
||||
bdyf[indexO++] = fi;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This seems to be a non-triangular face on the boundary
|
||||
// Consider this as "interior" and move on
|
||||
iidx[indexI] = faceIndex;
|
||||
intf[indexI++] = fi;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Face on the interior
|
||||
iidx[indexI] = faceIndex;
|
||||
intf[indexI++] = fi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Utility method to find the isolated point given two triangular faces.
|
||||
// - Returns the point on checkFace that does not belong to baseFace.
|
||||
inline label findIsolatedPoint
|
||||
(
|
||||
const face& baseFace,
|
||||
const face& checkFace
|
||||
)
|
||||
{
|
||||
// Get the fourth point
|
||||
forAll(checkFace, pointI)
|
||||
{
|
||||
if
|
||||
(
|
||||
checkFace[pointI] != baseFace[0] &&
|
||||
checkFace[pointI] != baseFace[1] &&
|
||||
checkFace[pointI] != baseFace[2]
|
||||
)
|
||||
{
|
||||
return checkFace[pointI];
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Utility method to find the isolated point on a triangular face
|
||||
// that doesn't lie on the specified edge. Also returns the point next to it.
|
||||
inline void findIsolatedPoint
|
||||
(
|
||||
const face& f,
|
||||
const edge& e,
|
||||
label& ptIndex,
|
||||
label& nextPtIndex
|
||||
)
|
||||
{
|
||||
// Check the first point
|
||||
if ( f[0] != e.start() && f[0] != e.end() )
|
||||
{
|
||||
ptIndex = f[0];
|
||||
nextPtIndex = f[1];
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the second point
|
||||
if ( f[1] != e.start() && f[1] != e.end() )
|
||||
{
|
||||
ptIndex = f[1];
|
||||
nextPtIndex = f[2];
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the third point
|
||||
if ( f[2] != e.start() && f[2] != e.end() )
|
||||
{
|
||||
ptIndex = f[2];
|
||||
nextPtIndex = f[0];
|
||||
return;
|
||||
}
|
||||
|
||||
// This bit should never happen.
|
||||
FatalErrorIn
|
||||
(
|
||||
"inline void meshOps::findIsolatedPoint"
|
||||
"(const face&, const edge&, label&, label&)"
|
||||
)
|
||||
<< "Cannot find isolated point in face " << f << endl
|
||||
<< " Using edge: " << e
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
// Given a face and cell index, find the apex point for a tet cell.
|
||||
inline label tetApexPoint
|
||||
(
|
||||
const label cIndex,
|
||||
const label fIndex,
|
||||
const UList<face>& faces,
|
||||
const UList<cell>& cells
|
||||
)
|
||||
{
|
||||
label apexPoint = -1;
|
||||
bool foundApex = false;
|
||||
|
||||
const cell& cellToCheck = cells[cIndex];
|
||||
const face& baseFace = faces[fIndex];
|
||||
|
||||
forAll(cellToCheck, faceI)
|
||||
{
|
||||
const face& faceToCheck = faces[cellToCheck[faceI]];
|
||||
|
||||
apexPoint = findIsolatedPoint(baseFace, faceToCheck);
|
||||
|
||||
if (apexPoint > -1)
|
||||
{
|
||||
foundApex = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundApex)
|
||||
{
|
||||
Pout<< "fIndex: " << fIndex << ":: " << faces[fIndex] << endl;
|
||||
Pout<< "cIndex: " << cIndex << ":: " << cellToCheck << endl;
|
||||
|
||||
forAll(cellToCheck, faceI)
|
||||
{
|
||||
Pout<< '\t' << cellToCheck[faceI] << ":: "
|
||||
<< faces[cellToCheck[faceI]] << endl;
|
||||
}
|
||||
|
||||
FatalErrorIn
|
||||
(
|
||||
"\n\n"
|
||||
"inline label meshOps::tetApexPoint\n"
|
||||
"(\n"
|
||||
" const label cIndex,\n"
|
||||
" const label fIndex,\n"
|
||||
" const UList<face>& faces,\n"
|
||||
" const UList<cell>& cells\n"
|
||||
")\n"
|
||||
)
|
||||
<< "Could not find an apex point in cell: " << cIndex
|
||||
<< " given face: " << fIndex
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
return apexPoint;
|
||||
}
|
||||
|
||||
|
||||
// Given a cell index, find the centroid / volume of a cell.
|
||||
// - If checking is enabled, return whether the cell is closed
|
||||
inline void cellCentreAndVolume
|
||||
(
|
||||
const label cIndex,
|
||||
const vectorField& points,
|
||||
const UList<face>& faces,
|
||||
const UList<cell>& cells,
|
||||
const UList<label>& owner,
|
||||
vector& centre,
|
||||
scalar& volume
|
||||
)
|
||||
{
|
||||
// Reset inputs
|
||||
volume = 0.0;
|
||||
centre = vector::zero;
|
||||
|
||||
const cell& cellToCheck = cells[cIndex];
|
||||
|
||||
// Average face-centres to get an estimate centroid
|
||||
vector cEst(vector::zero), fCentre(vector::zero);
|
||||
|
||||
forAll(cellToCheck, faceI)
|
||||
{
|
||||
const face& checkFace = faces[cellToCheck[faceI]];
|
||||
|
||||
cEst += checkFace.centre(points);
|
||||
}
|
||||
|
||||
cEst /= cellToCheck.size();
|
||||
|
||||
forAll(cellToCheck, faceI)
|
||||
{
|
||||
const face& checkFace = faces[cellToCheck[faceI]];
|
||||
|
||||
if (checkFace.size() == 3)
|
||||
{
|
||||
tetPointRef tpr
|
||||
(
|
||||
points[checkFace[2]],
|
||||
points[checkFace[1]],
|
||||
points[checkFace[0]],
|
||||
cEst
|
||||
);
|
||||
|
||||
scalar tetVol = tpr.mag();
|
||||
|
||||
// Flip if necessary
|
||||
if (owner[cellToCheck[faceI]] != cIndex)
|
||||
{
|
||||
tetVol *= -1.0;
|
||||
}
|
||||
|
||||
// Accumulate volume-weighted tet centre
|
||||
centre += tetVol*tpr.centre();
|
||||
|
||||
// Accumulate tet volume
|
||||
volume += tetVol;
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(checkFace, pI)
|
||||
{
|
||||
tetPointRef tpr
|
||||
(
|
||||
points[checkFace[pI]],
|
||||
points[checkFace.prevLabel(pI)],
|
||||
checkFace.centre(points),
|
||||
cEst
|
||||
);
|
||||
|
||||
scalar tetVol = tpr.mag();
|
||||
|
||||
// Flip if necessary
|
||||
if (owner[cellToCheck[faceI]] != cIndex)
|
||||
{
|
||||
tetVol *= -1.0;
|
||||
}
|
||||
|
||||
// Accumulate volume-weighted tet centre
|
||||
centre += tetVol*tpr.centre();
|
||||
|
||||
// Accumulate tet volume
|
||||
volume += tetVol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
centre /= volume + VSMALL;
|
||||
}
|
||||
|
||||
|
||||
// Determine whether a segment intersects a triangular face
|
||||
inline bool segmentTriFaceIntersection
|
||||
(
|
||||
const triPointRef& faceToCheck,
|
||||
const linePointRef& edgeToCheck,
|
||||
vector& intPoint
|
||||
)
|
||||
{
|
||||
// Fetch references
|
||||
const vector& p1 = edgeToCheck.start();
|
||||
const vector& p2 = edgeToCheck.end();
|
||||
|
||||
// Define face-normal
|
||||
vector n = faceToCheck.normal();
|
||||
n /= mag(n) + VSMALL;
|
||||
|
||||
// Compute uValue
|
||||
scalar numerator = n & (faceToCheck.a() - p1);
|
||||
scalar denominator = n & (p2 - p1);
|
||||
|
||||
// Check if the edge is parallel to the face
|
||||
if (mag(denominator) < VSMALL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
scalar u = (numerator / denominator);
|
||||
|
||||
// Check for intersection along line.
|
||||
if ((u >= 0.0) && (u <= 1.0))
|
||||
{
|
||||
// Compute point of intersection
|
||||
intPoint = p1 + u*(p2 - p1);
|
||||
|
||||
// Also make sure that intPoint lies within the face
|
||||
if (pointInTriFace(faceToCheck, intPoint, false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Failed to fall within edge-bounds, or within face
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Determine whether the particular point lies
|
||||
// inside the given triangular face
|
||||
inline bool pointInTriFace
|
||||
(
|
||||
const triPointRef& faceToCheck,
|
||||
const vector& cP,
|
||||
bool testCoplanarity
|
||||
)
|
||||
{
|
||||
// Copy inputs
|
||||
const vector& a = faceToCheck.a();
|
||||
const vector& b = faceToCheck.b();
|
||||
const vector& c = faceToCheck.c();
|
||||
|
||||
// Compute the normal
|
||||
vector nf = faceToCheck.normal();
|
||||
|
||||
if ( ((0.5 * ((b - a)^(cP - a))) & nf) < 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ((0.5 * ((c - b)^(cP - b))) & nf) < 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ((0.5 * ((a - c)^(cP - c))) & nf) < 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (testCoplanarity)
|
||||
{
|
||||
vector ftp(a - cP);
|
||||
|
||||
// Normalize vectors
|
||||
nf /= mag(nf) + VSMALL;
|
||||
ftp /= mag(ftp) + VSMALL;
|
||||
|
||||
if (mag(ftp & nf) > VSMALL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Passed test with all edges
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Parallel blocking send
|
||||
inline void pWrite
|
||||
(
|
||||
const label toID,
|
||||
const label& data
|
||||
)
|
||||
{
|
||||
OPstream::write
|
||||
(
|
||||
Pstream::blocking,
|
||||
toID,
|
||||
reinterpret_cast<const char*>(&data),
|
||||
sizeof(label)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Parallel blocking receive
|
||||
inline void pRead
|
||||
(
|
||||
const label fromID,
|
||||
label& data
|
||||
)
|
||||
{
|
||||
IPstream::read
|
||||
(
|
||||
Pstream::blocking,
|
||||
fromID,
|
||||
reinterpret_cast<char*>(&data),
|
||||
sizeof(label)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline void waitForBuffers()
|
||||
{
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
OPstream::waitRequests();
|
||||
IPstream::waitRequests();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Method to insert a label between two labels in a list
|
||||
// Assumes that all labels are unique.
|
||||
inline void insertLabel
|
||||
(
|
||||
const label newLabel,
|
||||
const label labelA,
|
||||
const label labelB,
|
||||
labelList& list
|
||||
)
|
||||
{
|
||||
// Create a new list
|
||||
bool found = false;
|
||||
label origSize = list.size();
|
||||
labelList newList(origSize + 1);
|
||||
|
||||
label index = 0, nextI = -1;
|
||||
|
||||
// Start a linear search
|
||||
forAll(list, itemI)
|
||||
{
|
||||
newList[index++] = list[itemI];
|
||||
|
||||
nextI = list.fcIndex(itemI);
|
||||
|
||||
if
|
||||
(
|
||||
(
|
||||
(list[itemI] == labelA && list[nextI] == labelB) ||
|
||||
(list[itemI] == labelB && list[nextI] == labelA)
|
||||
) &&
|
||||
!found
|
||||
)
|
||||
{
|
||||
found = true;
|
||||
newList[index++] = newLabel;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"inline void meshOps::insertLabel"
|
||||
"(const label, const label, const label, labelList&)"
|
||||
) << nl << "Cannot insert " << newLabel
|
||||
<< " in list: " << list << nl
|
||||
<< " Labels: "
|
||||
<< labelA << " and " << labelB
|
||||
<< " were not found in sequence."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Transfer the list
|
||||
list.transfer(newList);
|
||||
}
|
||||
|
||||
|
||||
// Utility method to replace a label in a given list
|
||||
inline void replaceLabel
|
||||
(
|
||||
const label original,
|
||||
const label replacement,
|
||||
labelList& list
|
||||
)
|
||||
{
|
||||
label index = -1;
|
||||
|
||||
if ((index = findIndex(list, original)) > -1)
|
||||
{
|
||||
list[index] = replacement;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"inline void label meshOps::replaceLabel"
|
||||
"(const label, const label, labelList&)"
|
||||
) << nl << "Cannot find " << original
|
||||
<< " in list: " << list << nl
|
||||
<< " Label: " << replacement
|
||||
<< " was not used in replacement."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End namespace meshOps
|
||||
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
Reference in a new issue