/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ 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 3 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, see .
\*---------------------------------------------------------------------------*/
#include "meshCutAndRemove.H"
#include "polyMesh.H"
#include "polyTopoChange.H"
#include "polyAddFace.H"
#include "polyAddPoint.H"
#include "polyRemovePoint.H"
#include "polyRemoveFace.H"
#include "polyModifyFace.H"
#include "cellCuts.H"
#include "mapPolyMesh.H"
#include "meshTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(meshCutAndRemove, 0);
}
// * * * * * * * * * * * * * Private Static Functions * * * * * * * * * * * //
// Returns -1 or index in elems1 of first shared element.
Foam::label Foam::meshCutAndRemove::firstCommon
(
const labelList& elems1,
const labelList& elems2
)
{
forAll(elems1, elemI)
{
label index1 = findIndex(elems2, elems1[elemI]);
if (index1 != -1)
{
return index1;
}
}
return -1;
}
// Check if twoCuts at two consecutive position in cuts.
bool Foam::meshCutAndRemove::isIn
(
const edge& twoCuts,
const labelList& cuts
)
{
label index = findIndex(cuts, twoCuts[0]);
if (index == -1)
{
return false;
}
return
(
cuts[cuts.fcIndex(index)] == twoCuts[1]
|| cuts[cuts.rcIndex(index)] == twoCuts[1]
);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::label Foam::meshCutAndRemove::findCutCell
(
const cellCuts& cuts,
const labelList& cellLabels
) const
{
forAll(cellLabels, labelI)
{
label celli = cellLabels[labelI];
if (cuts.cellLoops()[celli].size())
{
return celli;
}
}
return -1;
}
Foam::label Foam::meshCutAndRemove::findInternalFacePoint
(
const labelList& pointLabels
) const
{
forAll(pointLabels, labelI)
{
label pointI = pointLabels[labelI];
const labelList& pFaces = mesh().pointFaces()[pointI];
forAll(pFaces, pFaceI)
{
label facei = pFaces[pFaceI];
if (mesh().isInternalFace(facei))
{
return pointI;
}
}
}
if (pointLabels.empty())
{
FatalErrorInFunction
<< "Empty pointLabels" << abort(FatalError);
}
return -1;
}
Foam::label Foam::meshCutAndRemove::findPatchFacePoint
(
const face& f,
const label exposedPatchI
) const
{
const labelListList& pointFaces = mesh().pointFaces();
const polyBoundaryMesh& patches = mesh().boundaryMesh();
forAll(f, fp)
{
label pointI = f[fp];
if (pointI < mesh().nPoints())
{
const labelList& pFaces = pointFaces[pointI];
forAll(pFaces, i)
{
if (patches.whichPatch(pFaces[i]) == exposedPatchI)
{
return pointI;
}
}
}
}
return -1;
}
void Foam::meshCutAndRemove::faceCells
(
const cellCuts& cuts,
const label exposedPatchI,
const label facei,
label& own,
label& nei,
label& patchID
) const
{
const labelListList& anchorPts = cuts.cellAnchorPoints();
const labelListList& cellLoops = cuts.cellLoops();
const face& f = mesh().faces()[facei];
own = mesh().faceOwner()[facei];
if (cellLoops[own].size() && firstCommon(f, anchorPts[own]) == -1)
{
// owner has been split and this is the removed part.
own = -1;
}
nei = -1;
if (mesh().isInternalFace(facei))
{
nei = mesh().faceNeighbour()[facei];
if (cellLoops[nei].size() && firstCommon(f, anchorPts[nei]) == -1)
{
nei = -1;
}
}
patchID = mesh().boundaryMesh().whichPatch(facei);
if (patchID == -1 && (own == -1 || nei == -1))
{
// Face was internal but becomes external
patchID = exposedPatchI;
}
}
void Foam::meshCutAndRemove::getZoneInfo
(
const label facei,
label& zoneID,
bool& zoneFlip
) const
{
zoneID = mesh().faceZones().whichZone(facei);
zoneFlip = false;
if (zoneID >= 0)
{
const faceZone& fZone = mesh().faceZones()[zoneID];
zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
}
}
void Foam::meshCutAndRemove::addFace
(
polyTopoChange& meshMod,
const label facei,
const label masterPointI,
const face& newFace,
const label own,
const label nei,
const label patchID
)
{
label zoneID;
bool zoneFlip;
getZoneInfo(facei, zoneID, zoneFlip);
if ((nei == -1) || (own != -1 && own < nei))
{
// Ordering ok.
if (debug & 2)
{
Pout<< "Adding face " << newFace
<< " with new owner:" << own
<< " with new neighbour:" << nei
<< " patchID:" << patchID
<< " anchor:" << masterPointI
<< " zoneID:" << zoneID
<< " zoneFlip:" << zoneFlip
<< endl;
}
meshMod.setAction
(
polyAddFace
(
newFace, // face
own, // owner
nei, // neighbour
masterPointI, // master point
-1, // master edge
-1, // master face for addition
false, // flux flip
patchID, // patch for face
zoneID, // zone for face
zoneFlip // face zone flip
)
);
}
else
{
// Reverse owner/neighbour
if (debug & 2)
{
Pout<< "Adding (reversed) face " << newFace.reverseFace()
<< " with new owner:" << nei
<< " with new neighbour:" << own
<< " patchID:" << patchID
<< " anchor:" << masterPointI
<< " zoneID:" << zoneID
<< " zoneFlip:" << zoneFlip
<< endl;
}
meshMod.setAction
(
polyAddFace
(
newFace.reverseFace(), // face
nei, // owner
own, // neighbour
masterPointI, // master point
-1, // master edge
-1, // master face for addition
false, // flux flip
patchID, // patch for face
zoneID, // zone for face
zoneFlip // face zone flip
)
);
}
}
// Modifies existing facei for either new owner/neighbour or new face points.
void Foam::meshCutAndRemove::modFace
(
polyTopoChange& meshMod,
const label facei,
const face& newFace,
const label own,
const label nei,
const label patchID
)
{
label zoneID;
bool zoneFlip;
getZoneInfo(facei, zoneID, zoneFlip);
if
(
(own != mesh().faceOwner()[facei])
|| (
mesh().isInternalFace(facei)
&& (nei != mesh().faceNeighbour()[facei])
)
|| (newFace != mesh().faces()[facei])
)
{
if (debug & 2)
{
Pout<< "Modifying face " << facei
<< " old vertices:" << mesh().faces()[facei]
<< " new vertices:" << newFace
<< " new owner:" << own
<< " new neighbour:" << nei
<< " new patch:" << patchID
<< " new zoneID:" << zoneID
<< " new zoneFlip:" << zoneFlip
<< endl;
}
if ((nei == -1) || (own != -1 && own < nei))
{
meshMod.setAction
(
polyModifyFace
(
newFace, // modified face
facei, // label of face being modified
own, // owner
nei, // neighbour
false, // face flip
patchID, // patch for face
false, // remove from zone
zoneID, // zone for face
zoneFlip // face flip in zone
)
);
}
else
{
meshMod.setAction
(
polyModifyFace
(
newFace.reverseFace(), // modified face
facei, // label of face being modified
nei, // owner
own, // neighbour
false, // face flip
patchID, // patch for face
false, // remove from zone
zoneID, // zone for face
zoneFlip // face flip in zone
)
);
}
}
}
void Foam::meshCutAndRemove::copyFace
(
const face& f,
const label startFp,
const label endFp,
face& newFace
) const
{
label fp = startFp;
label newFp = 0;
while (fp != endFp)
{
newFace[newFp++] = f[fp];
fp = (fp + 1) % f.size();
}
newFace[newFp] = f[fp];
}
// Actually split face in two along splitEdge v0, v1 (the two vertices in new
// vertex numbering). Generates faces in same ordering
// as original face. Replaces cutEdges by the points introduced on them
// (addedPoints_).
void Foam::meshCutAndRemove::splitFace
(
const face& f,
const label v0,
const label v1,
face& f0,
face& f1
) const
{
// Check if we find any new vertex which is part of the splitEdge.
label startFp = findIndex(f, v0);
if (startFp == -1)
{
FatalErrorInFunction
<< "Cannot find vertex (new numbering) " << v0
<< " on face " << f
<< abort(FatalError);
}
label endFp = findIndex(f, v1);
if (endFp == -1)
{
FatalErrorInFunction
<< "Cannot find vertex (new numbering) " << v1
<< " on face " << f
<< abort(FatalError);
}
f0.setSize((endFp + 1 + f.size() - startFp) % f.size());
f1.setSize(f.size() - f0.size() + 2);
copyFace(f, startFp, endFp, f0);
copyFace(f, endFp, startFp, f1);
}
Foam::face Foam::meshCutAndRemove::addEdgeCutsToFace(const label facei) const
{
const face& f = mesh().faces()[facei];
face newFace(2 * f.size());
label newFp = 0;
forAll(f, fp)
{
// Duplicate face vertex.
newFace[newFp++] = f[fp];
// Check if edge has been cut.
label fp1 = f.fcIndex(fp);
HashTable