COMP: localPointRegion: moved to meshTools to break circular dep

This commit is contained in:
mattijs
2013-08-12 12:39:38 +01:00
parent 82941460e7
commit bb0ace809d
5 changed files with 3 additions and 5 deletions

View File

@ -53,6 +53,7 @@ $(meshWave)/FaceCellWaveName.C
regionSplit/regionSplit.C
regionSplit/localPointRegion.C
indexedOctree/treeDataEdge.C
indexedOctree/treeDataFace.C

View File

@ -0,0 +1,622 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "localPointRegion.H"
#include "syncTools.H"
#include "polyMesh.H"
#include "mapPolyMesh.H"
#include "globalIndex.H"
#include "indirectPrimitivePatch.H"
#include "dummyTransform.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(localPointRegion, 0);
// Reduction class to get minimum value over face.
class minEqOpFace
{
public:
void operator()(face& x, const face& y) const
{
if (x.size())
{
label j = 0;
forAll(x, i)
{
x[i] = min(x[i], y[j]);
j = y.rcIndex(j);
}
}
}
};
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Are two lists identical either in forward or in reverse order.
bool Foam::localPointRegion::isDuplicate
(
const face& f0,
const face& f1,
const bool forward
)
{
label fp1 = findIndex(f1, f0[0]);
if (fp1 == -1)
{
return false;
}
forAll(f0, fp0)
{
if (f0[fp0] != f1[fp1])
{
return false;
}
if (forward)
{
fp1 = f1.fcIndex(fp1);
}
else
{
fp1 = f1.rcIndex(fp1);
}
}
return true;
}
// Count regions per point
void Foam::localPointRegion::countPointRegions
(
const polyMesh& mesh,
const boolList& candidatePoint,
const Map<label>& candidateFace,
faceList& minRegion
)
{
// Almost all will have only one so only
// populate Map if more than one.
labelList minPointRegion(mesh.nPoints(), -1);
// From global point to local (multi-region) point numbering
meshPointMap_.resize(candidateFace.size()/100);
// From local (multi-region) point to regions
DynamicList<labelList> pointRegions(meshPointMap_.size());
// From faces with any duplicated point on it to local face
meshFaceMap_.resize(meshPointMap_.size());
forAllConstIter(Map<label>, candidateFace, iter)
{
label faceI = iter.key();
if (!mesh.isInternalFace(faceI))
{
const face& f = mesh.faces()[faceI];
if (minRegion[faceI].empty())
{
FatalErrorIn("localPointRegion::countPointRegions(..)")
<< "Face from candidateFace without minRegion set." << endl
<< "Face:" << faceI << " fc:" << mesh.faceCentres()[faceI]
<< " verts:" << f << abort(FatalError);
}
forAll(f, fp)
{
label pointI = f[fp];
// Even points which were not candidates for splitting might
// be on multiple baffles that are being split so check.
if (candidatePoint[pointI])
{
label region = minRegion[faceI][fp];
if (minPointRegion[pointI] == -1)
{
minPointRegion[pointI] = region;
}
else if (minPointRegion[pointI] != region)
{
// Multiple regions for this point. Add.
Map<label>::iterator iter = meshPointMap_.find(pointI);
if (iter != meshPointMap_.end())
{
labelList& regions = pointRegions[iter()];
if (findIndex(regions, region) == -1)
{
label sz = regions.size();
regions.setSize(sz+1);
regions[sz] = region;
}
}
else
{
label localPointI = meshPointMap_.size();
meshPointMap_.insert(pointI, localPointI);
labelList regions(2);
regions[0] = minPointRegion[pointI];
regions[1] = region;
pointRegions.append(regions);
}
label meshFaceMapI = meshFaceMap_.size();
meshFaceMap_.insert(faceI, meshFaceMapI);
}
}
}
}
}
minPointRegion.clear();
// Add internal faces that use any duplicated point. Can only have one
// region!
forAllConstIter(Map<label>, candidateFace, iter)
{
label faceI = iter.key();
if (mesh.isInternalFace(faceI))
{
const face& f = mesh.faces()[faceI];
forAll(f, fp)
{
// Note: candidatePoint test not really necessary but
// speeds up rejection.
if (candidatePoint[f[fp]] && meshPointMap_.found(f[fp]))
{
label meshFaceMapI = meshFaceMap_.size();
meshFaceMap_.insert(faceI, meshFaceMapI);
}
}
}
}
// Transfer to member data
pointRegions.shrink();
pointRegions_.setSize(pointRegions.size());
forAll(pointRegions, i)
{
pointRegions_[i].transfer(pointRegions[i]);
}
// Compact minRegion
faceRegions_.setSize(meshFaceMap_.size());
forAllConstIter(Map<label>, meshFaceMap_, iter)
{
faceRegions_[iter()].labelList::transfer(minRegion[iter.key()]);
//// Print a bit
//{
// label faceI = iter.key();
// const face& f = mesh.faces()[faceI];
// Pout<< "Face:" << faceI << " fc:" << mesh.faceCentres()[faceI]
// << " verts:" << f << endl;
// forAll(f, fp)
// {
// Pout<< " " << f[fp] << " min:" << faceRegions_[iter()][fp]
// << endl;
// }
// Pout<< endl;
//}
}
// Compact region numbering
// ? TBD.
}
void Foam::localPointRegion::calcPointRegions
(
const polyMesh& mesh,
boolList& candidatePoint
)
{
label nBnd = mesh.nFaces()-mesh.nInternalFaces();
const labelList& faceOwner = mesh.faceOwner();
const labelList& faceNeighbour = mesh.faceNeighbour();
syncTools::syncPointList
(
mesh,
candidatePoint,
orEqOp<bool>(),
false // nullValue
);
// Mark any face/boundaryFace/cell with a point on a candidate point.
// - candidateFace does not necessary have to be a baffle!
// - candidateFace is synchronised (since candidatePoint is)
Map<label> candidateFace(2*nBnd);
label candidateFaceI = 0;
Map<label> candidateCell(nBnd);
label candidateCellI = 0;
forAll(mesh.faces(), faceI)
{
const face& f = mesh.faces()[faceI];
forAll(f, fp)
{
if (candidatePoint[f[fp]])
{
// Mark face
if (candidateFace.insert(faceI, candidateFaceI))
{
candidateFaceI++;
}
// Mark cells
if (candidateCell.insert(faceOwner[faceI], candidateCellI))
{
candidateCellI++;
}
if (mesh.isInternalFace(faceI))
{
label nei = faceNeighbour[faceI];
if (candidateCell.insert(nei, candidateCellI))
{
candidateCellI++;
}
}
break;
}
}
}
// Get global indices for cells
globalIndex globalCells(mesh.nCells());
// Determine for every candidate face per point the minimum region
// (global cell) it is connected to. (candidateFaces are the
// only ones using a
// candidate point so the only ones that can be affected)
faceList minRegion(mesh.nFaces());
forAllConstIter(Map<label>, candidateFace, iter)
{
label faceI = iter.key();
const face& f = mesh.faces()[faceI];
if (mesh.isInternalFace(faceI))
{
label globOwn = globalCells.toGlobal(faceOwner[faceI]);
label globNei = globalCells.toGlobal(faceNeighbour[faceI]);
minRegion[faceI].setSize(f.size(), min(globOwn, globNei));
}
else
{
label globOwn = globalCells.toGlobal(faceOwner[faceI]);
minRegion[faceI].setSize(f.size(), globOwn);
}
}
// Now minimize over all faces that are connected through internal
// faces or through cells. This loop iterates over the max number of
// cells connected to a point (=8 for hex mesh)
while (true)
{
// Transport minimum from face across cell
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Map<label> minPointValue(100);
label nChanged = 0;
forAllConstIter(Map<label>, candidateCell, iter)
{
minPointValue.clear();
label cellI = iter.key();
const cell& cFaces = mesh.cells()[cellI];
// Determine minimum per point
forAll(cFaces, cFaceI)
{
label faceI = cFaces[cFaceI];
if (minRegion[faceI].size())
{
const face& f = mesh.faces()[faceI];
forAll(f, fp)
{
label pointI = f[fp];
Map<label>::iterator iter = minPointValue.find(pointI);
if (iter == minPointValue.end())
{
minPointValue.insert(pointI, minRegion[faceI][fp]);
}
else
{
label currentMin = iter();
iter() = min(currentMin, minRegion[faceI][fp]);
}
}
}
}
// Set face minimum from point minimum
forAll(cFaces, cFaceI)
{
label faceI = cFaces[cFaceI];
if (minRegion[faceI].size())
{
const face& f = mesh.faces()[faceI];
forAll(f, fp)
{
label minVal = minPointValue[f[fp]];
if (minVal != minRegion[faceI][fp])
{
minRegion[faceI][fp] = minVal;
nChanged++;
}
}
}
}
}
//Pout<< "nChanged:" << nChanged << endl;
if (returnReduce(nChanged, sumOp<label>()) == 0)
{
break;
}
// Transport minimum across coupled faces
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SubList<face> l
(
minRegion,
mesh.nFaces()-mesh.nInternalFaces(),
mesh.nInternalFaces()
);
syncTools::syncBoundaryFaceList
(
mesh,
l,
minEqOpFace(),
Foam::dummyTransform() // dummy transformation
);
}
// Count regions per point
countPointRegions(mesh, candidatePoint, candidateFace, minRegion);
minRegion.clear();
//// Print points with multiple regions. These points need to be duplicated.
//forAllConstIter(Map<label>, meshPointMap_, iter)
//{
// Pout<< "point:" << iter.key()
// << " coord:" << mesh.points()[iter.key()]
// << " regions:" << pointRegions_[iter()] << endl;
//}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::localPointRegion::localPointRegion(const polyMesh& mesh)
:
//nRegions_(0),
meshPointMap_(0),
pointRegions_(0),
meshFaceMap_(0),
faceRegions_(0)
{
const polyBoundaryMesh& patches = mesh.boundaryMesh();
// Get any point on the outside which is on a non-coupled boundary
boolList candidatePoint(mesh.nPoints(), false);
forAll(patches, patchI)
{
if (!patches[patchI].coupled())
{
const polyPatch& pp = patches[patchI];
forAll(pp.meshPoints(), i)
{
candidatePoint[pp.meshPoints()[i]] = true;
}
}
}
calcPointRegions(mesh, candidatePoint);
}
Foam::localPointRegion::localPointRegion
(
const polyMesh& mesh,
const labelList& candidatePoints
)
:
//nRegions_(0),
meshPointMap_(0),
pointRegions_(0),
meshFaceMap_(0),
faceRegions_(0)
{
boolList candidatePoint(mesh.nPoints(), false);
forAll(candidatePoints, i)
{
candidatePoint[candidatePoints[i]] = true;
}
calcPointRegions(mesh, candidatePoint);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Return a list (in allPatch indices) with either -1 or the face label
// of the face that uses the same vertices.
Foam::labelList Foam::localPointRegion::findDuplicateFaces
(
const primitiveMesh& mesh,
const labelList& boundaryFaces
)
{
// Addressing engine for all boundary faces.
indirectPrimitivePatch allPatch
(
IndirectList<face>(mesh.faces(), boundaryFaces),
mesh.points()
);
labelList duplicateFace(allPatch.size(), -1);
label nDuplicateFaces = 0;
// Find all duplicate faces.
forAll(allPatch, bFaceI)
{
const face& f = allPatch.localFaces()[bFaceI];
// Get faces connected to f[0].
// Check whether share all points with f.
const labelList& pFaces = allPatch.pointFaces()[f[0]];
forAll(pFaces, i)
{
label otherFaceI = pFaces[i];
if (otherFaceI > bFaceI)
{
const face& otherF = allPatch.localFaces()[otherFaceI];
if (isDuplicate(f, otherF, true))
{
FatalErrorIn
(
"findDuplicateFaces(const primitiveMesh&"
", const labelList&)"
) << "Face:" << bFaceI + mesh.nInternalFaces()
<< " has local points:" << f
<< " which are in same order as face:"
<< otherFaceI + mesh.nInternalFaces()
<< " with local points:" << otherF
<< abort(FatalError);
}
else if (isDuplicate(f, otherF, false))
{
label meshFace0 = bFaceI + mesh.nInternalFaces();
label meshFace1 = otherFaceI + mesh.nInternalFaces();
if
(
duplicateFace[bFaceI] != -1
|| duplicateFace[otherFaceI] != -1
)
{
FatalErrorIn
(
"findDuplicateFaces(const primitiveMesh&"
", const labelList&)"
) << "One of two duplicate faces already marked"
<< " as duplicate." << nl
<< "This means that three or more faces share"
<< " the same points and this is illegal." << nl
<< "Face:" << meshFace0
<< " with local points:" << f
<< " which are in same order as face:"
<< meshFace1
<< " with local points:" << otherF
<< abort(FatalError);
}
duplicateFace[bFaceI] = otherFaceI;
duplicateFace[otherFaceI] = bFaceI;
nDuplicateFaces++;
}
}
}
}
return duplicateFace;
}
void Foam::localPointRegion::updateMesh(const mapPolyMesh& map)
{
{
Map<label> newMap(meshFaceMap_.size());
forAllConstIter(Map<label>, meshFaceMap_, iter)
{
label newFaceI = map.reverseFaceMap()[iter.key()];
if (newFaceI >= 0)
{
newMap.insert(newFaceI, iter());
}
}
meshFaceMap_.transfer(newMap);
}
{
Map<label> newMap(meshPointMap_.size());
forAllConstIter(Map<label>, meshPointMap_, iter)
{
label newPointI = map.reversePointMap()[iter.key()];
if (newPointI >= 0)
{
newMap.insert(newPointI, iter());
}
}
meshPointMap_.transfer(newMap);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,201 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 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 <http://www.gnu.org/licenses/>.
Class
Foam::localPointRegion
Description
Takes mesh with 'baffles' (= boundary faces sharing points).
Determines for selected points on boundary faces the 'point region' it is
connected to. Each region can be visited by a cell-face-cell walk.
Used in duplicating points after splitting baffles.
Regions are not consecutive per processor. They will be -1..nRegions_.
Note: coupled boundaries (cyclics, parallel) not fully tested.
SourceFiles
localPointRegion.C
\*---------------------------------------------------------------------------*/
#ifndef localPointRegion_H
#define localPointRegion_H
#include "typeInfo.H"
#include "Map.H"
#include "labelList.H"
#include "HashSet.H"
#include "faceList.H"
#include "boolList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class primitiveMesh;
class polyMesh;
class face;
class mapPolyMesh;
/*---------------------------------------------------------------------------*\
Class localPointRegion Declaration
\*---------------------------------------------------------------------------*/
class localPointRegion
{
// Private data
////- (global) number of regions
//label nRegions_;
//- Per point that is to duplicated to the local index
Map<label> meshPointMap_;
//- Per local point the regions it is in
labelListList pointRegions_;
//- Per face that uses a duplicated point the local index
Map<label> meshFaceMap_;
//- Per face the region of its points
faceList faceRegions_;
// Private Member Functions
//- Given minimum cell the points on a face are connected to
// determine the points to be duplicated.
void countPointRegions
(
const polyMesh& mesh,
const boolList& candidatePoint,
const Map<label>& candidateFace,
faceList& minRegion
);
//- Do all: calculate points that need to be duplicated.
void calcPointRegions
(
const polyMesh& mesh,
boolList& candidatePoint
);
//- Check if two faces are equal. If forward = false checks f1 in
// reverse order.
static bool isDuplicate
(
const face& f0,
const face& f1,
const bool forward
);
public:
//- Runtime type information
ClassName("localPointRegion");
// Constructors
//- Construct from mesh. Assumes all non-coupled boundary points
// are candidates for duplication
localPointRegion(const polyMesh& mesh);
//- Construct from mesh and candidate points for duplication
localPointRegion
(
const polyMesh& mesh,
const labelList& candidatePoints
);
// Member Functions
// Static Member Functions
//- Helper routine to find baffles (two boundary faces using the
// same points but in reverse order)
// Gets list of (boundary!) faces to check. Returns labelList
// of same size as the input list
// with -1 or index of other face in the input list.
// Does not handle duplicate faces on both sides of processor patch
static labelList findDuplicateFaces
(
const primitiveMesh&,
const labelList&
);
// Access
////- Global number of regions. TBD. regions not compacted yet.
//label nRegions() const
//{
// return nRegions_;
//}
//- Per point that is to be duplicated the local index
const Map<label>& meshPointMap() const
{
return meshPointMap_;
}
//- Per local point the regions it is in
const labelListList& pointRegions() const
{
return pointRegions_;
}
//- Per face that uses a duplicated point the local index
const Map<label>& meshFaceMap() const
{
return meshFaceMap_;
}
//- Per face the region of its points
const faceList& faceRegions() const
{
return faceRegions_;
}
// Edit
//- Force recalculation of locally stored data on topological change
void updateMesh(const mapPolyMesh&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //